OZO 「お象」
Boost.Asio and libpq based asynchronous PostgreSQL unofficial header-only C++17 client library.
options.h
1 #pragma once
2 
3 #include <boost/hana/is_empty.hpp>
4 #include <boost/hana/tuple.hpp>
5 #include <boost/hana/fold.hpp>
6 #include <boost/hana/concat.hpp>
7 #include <boost/hana/map.hpp>
8 
9 namespace ozo {
10 
11 namespace hana = boost::hana;
12 
32 template <typename Key>
33 struct option : hana::type<Key> {
34  template <typename T>
35  constexpr auto operator = (T&& v) const {
36  return hana::make_pair(*this, std::forward<T>(v));
37  }
38 };
39 
51 template <typename Map, typename Key>
52 constexpr decltype(auto) get_option(Map&& map, ozo::option<Key> op) {
53  static_assert(decltype(hana::is_a<hana::map_tag>(map))::value, "Map should be boost::hana::map");
54  static_assert(decltype(hana::contains(map, op))::value, "option has not been found");
55  return map[op];
56 }
57 
69 template <typename Map, typename Key, typename T>
70 constexpr decltype(auto) get_option(Map&& map, ozo::option<Key> op, T&& default_) {
71  static_assert(decltype(hana::is_a<hana::map_tag>(map))::value, "Map should be boost::hana::map");
72  if constexpr (decltype(hana::contains(map, op))::value) {
73  return map[op];
74  } else {
75  return std::forward<T>(default_);
76  }
77 }
78 
104 template <typename ...Options>
105 constexpr auto make_options(Options&& ...opts) {
106  return hana::make_map(std::forward<Options>(opts)...);
107 }
108 
120 template <typename RealType, typename Options>
122  Options v_;
123 
124  template <typename OtherOptions>
125  constexpr static auto rebind(OtherOptions&& v) {
126  return RealType::rebind_options(std::forward<OtherOptions>(v));
127  }
128 
129 public:
135  constexpr options_factory_base(Options v) : v_(std::move(v)) {
136  static_assert(decltype(hana::is_a<hana::map_tag>(v))::value, "Options should be boost::hana::map");
137  }
138 
167 #ifdef OZO_DOCUMENTATION
168  template <typename Options>
169  constexpr decltype(auto) set(Options&& ...options) &&;
170 #endif
171  template <typename Key, typename T>
172  constexpr decltype(auto) set(hana::pair<ozo::option<Key>, T> v) && {
173  if constexpr (decltype(has(hana::first(v)))::value) {
174  v_[hana::first(v)] = std::move(hana::second(std::move(v)));
175  return static_cast<RealType&&>(*this);
176  } else {
177  return rebind(hana::insert(std::move(v_), std::move(v)));
178  }
179  }
180 
181  template <typename Key1, typename T1, typename Key2, typename T2, typename ...Ts>
182  constexpr decltype(auto) set(hana::pair<ozo::option<Key1>, T1> v1, hana::pair<ozo::option<Key2>, T2> v2, Ts ...vs) && {
183  return hana::fold(
184  hana::make_tuple(std::move(v1), std::move(v2), std::move(vs)...),
185  std::move(*this),
186  [](auto self, auto v) { return std::move(self).set(v);}
187  );
188  }
189 
190  template <typename Key, typename T, typename ...Ts>
191  constexpr decltype(auto) set(hana::pair<ozo::option<Key>, T> v, Ts ...vs) const & {
192  auto copy = *this;
193  return std::move(copy).set(std::move(v), std::move(vs)...);
194  }
195 
196  template <typename Key, typename T>
197  constexpr decltype(auto) set(ozo::option<Key> op, T&& value) && {
198  return std::move(*this).set(hana::make_pair(op, std::forward<T>(value)));
199  }
200 
201  template <typename Key, typename T>
202  constexpr decltype(auto) set(ozo::option<Key> op, T&& value) const & {
203  return set(hana::make_pair(op, std::forward<T>(value)));
204  }
205 
231  template <typename Key>
232  constexpr auto has(ozo::option<Key> op) const {
233  return hana::contains(options(), op);
234  }
235 
242  template <typename Key>
243  constexpr decltype(auto) get(ozo::option<Key> op) const {
244  return get_option(options(), op);
245  }
246 
250  constexpr const Options& options() const & { return v_;}
254  constexpr Options& options() & { return v_;}
258  constexpr Options&& options() && { return std::move(v_);}
259 };
260 
269 template <typename Options = decltype(hana::make_map())>
270 class options_factory : public ozo::options_factory_base<options_factory<Options>, Options> {
272  friend class ozo::options_factory_base<options_factory<Options>, Options>;
273 
274  template <typename OtherOptions>
275  constexpr static auto rebind_options(OtherOptions&& options) {
276  return options_factory<std::decay_t<OtherOptions>>(std::forward<OtherOptions>(options));
277  }
278 
279 public:
285  constexpr options_factory(Options options = Options{}) : base(std::move(options)) {
286  options_factory(decltype(hana::is_a<hana::map_tag>(options))::value, "Options should be boost::hana::map");
287  }
288 };
289 
290 } // namespace ozo
ozo::options_factory_base::options
constexpr Options & options() &
Definition: options.h:254
ozo::options_factory_base::options
constexpr Options && options() &&
Definition: options.h:258
ozo::make_options
constexpr auto make_options(Options &&...opts)
Constructor for options map.
Definition: options.h:105
ozo::options_factory_base::get
constexpr decltype(auto) get(ozo::option< Key > op) const
Definition: options.h:243
ozo::options_factory
Generic options factory.
Definition: options.h:270
ozo::options_factory::options_factory
constexpr options_factory(Options options=Options{})
Definition: options.h:285
ozo::options_factory_base::options_factory_base
constexpr options_factory_base(Options v)
Definition: options.h:135
ozo::value
Database request result value proxy.
Definition: result.h:25
ozo::options_factory_base
Base class for options factories.
Definition: options.h:121
ozo::option
Option class.
Definition: options.h:33
ozo::get_option
constexpr decltype(auto) get_option(Map &&map, ozo::option< Key > op, T &&default_)
Get the option object from Hana.Map.
Definition: options.h:70
ozo::options_factory_base::options
constexpr const Options & options() const &
Definition: options.h:250
ozo::options_factory_base::set
constexpr decltype(auto) set(Options &&...options) &&
ozo::options_factory_base::has
constexpr auto has(ozo::option< Key > op) const
Definition: options.h:232