optional.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. /*!
  2. @file
  3. Forward declares `boost::hana::optional`.
  4. Copyright Louis Dionne 2013-2022
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef BOOST_HANA_FWD_OPTIONAL_HPP
  9. #define BOOST_HANA_FWD_OPTIONAL_HPP
  10. #include <boost/hana/config.hpp>
  11. #include <boost/hana/detail/operators/adl.hpp>
  12. #include <boost/hana/fwd/core/make.hpp>
  13. namespace boost { namespace hana {
  14. //! @ingroup group-datatypes
  15. //! Optional value whose optional-ness is known at compile-time.
  16. //!
  17. //! An `optional` either contains a value (represented as `just(x)`), or
  18. //! it is empty (represented as `nothing`). In essence, `hana::optional`
  19. //! is pretty much like a `boost::optional` or the upcoming `std::optional`,
  20. //! except for the fact that whether a `hana::optional` is empty or not is
  21. //! known at compile-time. This can be particularly useful for returning
  22. //! from a function that might fail, but whose reason for failing is not
  23. //! important. Of course, whether the function will fail has to be known
  24. //! at compile-time.
  25. //!
  26. //! This is really an important difference between `hana::optional` and
  27. //! `std::optional`. Unlike `std::optional<T>{}` and `std::optional<T>{x}`
  28. //! who share the same type (`std::optional<T>`), `hana::just(x)` and
  29. //! `hana::nothing` do not share the same type, since the state of the
  30. //! optional has to be known at compile-time. Hence, whether a `hana::just`
  31. //! or a `hana::nothing` will be returned from a function has to be known
  32. //! at compile-time for the return type of that function to be computable
  33. //! by the compiler. This makes `hana::optional` well suited for static
  34. //! metaprogramming tasks, but very poor for anything dynamic.
  35. //!
  36. //! @note
  37. //! When you use a container, remember not to make assumptions about its
  38. //! representation, unless the documentation gives you those guarantees.
  39. //! More details [in the tutorial](@ref tutorial-containers-types).
  40. //!
  41. //!
  42. //! Interoperation with `type`s
  43. //! ---------------------------
  44. //! When a `just` contains an object of type `T` which is a `type`,
  45. //! it has a nested `::%type` alias equivalent to `T::%type`. `nothing`,
  46. //! however, never has a nested `::%type` alias. If `t` is a `type`,
  47. //! this allows `decltype(just(t))` to be seen as a nullary metafunction
  48. //! equivalent to `decltype(t)`. Along with the `sfinae` function,
  49. //! this allows `hana::optional` to interact seamlessly with
  50. //! SFINAE-friendly metafunctions.
  51. //! Example:
  52. //! @include example/optional/sfinae_friendly_metafunctions.cpp
  53. //!
  54. //!
  55. //! Modeled concepts
  56. //! ----------------
  57. //! 1. `Comparable`\n
  58. //! Two `optional`s are equal if and only if they are both empty or they
  59. //! both contain a value and those values are equal.
  60. //! @include example/optional/comparable.cpp
  61. //!
  62. //! 2. `Orderable`\n
  63. //! Optional values can be ordered by considering the value they are
  64. //! holding, if any. To handle the case of an empty optional value, we
  65. //! arbitrarily set `nothing` as being less than any other `just`. Hence,
  66. //! @code
  67. //! just(x) < just(y) if and only if x < y
  68. //! nothing < just(anything)
  69. //! @endcode
  70. //! Example:
  71. //! @include example/optional/orderable.cpp
  72. //!
  73. //! 3. `Functor`\n
  74. //! An optional value can be seen as a list containing either one element
  75. //! (`just(x)`) or no elements at all (`nothing`). As such, mapping
  76. //! a function over an optional value is equivalent to applying it to
  77. //! its value if there is one, and to `nothing` otherwise:
  78. //! @code
  79. //! transform(just(x), f) == just(f(x))
  80. //! transform(nothing, f) == nothing
  81. //! @endcode
  82. //! Example:
  83. //! @include example/optional/functor.cpp
  84. //!
  85. //! 4. `Applicative`\n
  86. //! First, a value can be made optional with `lift<optional_tag>`, which
  87. //! is equivalent to `just`. Second, one can feed an optional value to an
  88. //! optional function with `ap`, which will return `just(f(x))` if there
  89. //! is both a function _and_ a value, and `nothing` otherwise:
  90. //! @code
  91. //! ap(just(f), just(x)) == just(f(x))
  92. //! ap(nothing, just(x)) == nothing
  93. //! ap(just(f), nothing) == nothing
  94. //! ap(nothing, nothing) == nothing
  95. //! @endcode
  96. //! A simple example:
  97. //! @include example/optional/applicative.cpp
  98. //! A more complex example:
  99. //! @include example/optional/applicative.complex.cpp
  100. //!
  101. //! 5. `Monad`\n
  102. //! The `Monad` model makes it easy to compose actions that might fail.
  103. //! One can feed an optional value if there is one into a function with
  104. //! `chain`, which will return `nothing` if there is no value. Finally,
  105. //! optional-optional values can have their redundant level of optionality
  106. //! removed with `flatten`. Also note that the `|` operator can be used in
  107. //! place of the `chain` function.
  108. //! Example:
  109. //! @include example/optional/monad.cpp
  110. //!
  111. //! 6. `MonadPlus`\n
  112. //! The `MonadPlus` model allows choosing the first valid value out of
  113. //! two optional values with `concat`. If both optional values are
  114. //! `nothing`s, `concat` will return `nothing`.
  115. //! Example:
  116. //! @include example/optional/monad_plus.cpp
  117. //!
  118. //! 7. `Foldable`\n
  119. //! Folding an optional value is equivalent to folding a list containing
  120. //! either no elements (for `nothing`) or `x` (for `just(x)`).
  121. //! Example:
  122. //! @include example/optional/foldable.cpp
  123. //!
  124. //! 8. `Searchable`\n
  125. //! Searching an optional value is equivalent to searching a list
  126. //! containing `x` for `just(x)` and an empty list for `nothing`.
  127. //! Example:
  128. //! @include example/optional/searchable.cpp
  129. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  130. template <typename ...T>
  131. struct optional {
  132. // 5.3.1, Constructors
  133. //! Default-construct an `optional`. Only exists if the optional
  134. //! contains a value, and if that value is DefaultConstructible.
  135. constexpr optional() = default;
  136. //! Copy-construct an `optional`.
  137. //! An empty optional may only be copy-constructed from another
  138. //! empty `optional`, and an `optional` with a value may only be
  139. //! copy-constructed from another `optional` with a value.
  140. //! Furthermore, this constructor only exists if the value
  141. //! held in the `optional` is CopyConstructible.
  142. optional(optional const&) = default;
  143. //! Move-construct an `optional`.
  144. //! An empty optional may only be move-constructed from another
  145. //! empty `optional`, and an `optional` with a value may only be
  146. //! move-constructed from another `optional` with a value.
  147. //! Furthermore, this constructor only exists if the value
  148. //! held in the `optional` is MoveConstructible.
  149. optional(optional&&) = default;
  150. //! Construct an `optional` holding a value of type `T` from another
  151. //! object of type `T`. The value is copy-constructed.
  152. constexpr optional(T const& t)
  153. : value_(t)
  154. { }
  155. //! Construct an `optional` holding a value of type `T` from another
  156. //! object of type `T`. The value is move-constructed.
  157. constexpr optional(T&& t)
  158. : value_(static_cast<T&&>(t))
  159. { }
  160. // 5.3.3, Assignment
  161. //! Copy-assign an `optional`.
  162. //! An empty optional may only be copy-assigned from another empty
  163. //! `optional`, and an `optional` with a value may only be copy-assigned
  164. //! from another `optional` with a value. Furthermore, this assignment
  165. //! operator only exists if the value held in the `optional` is
  166. //! CopyAssignable.
  167. constexpr optional& operator=(optional const&) = default;
  168. //! Move-assign an `optional`.
  169. //! An empty optional may only be move-assigned from another empty
  170. //! `optional`, and an `optional` with a value may only be move-assigned
  171. //! from another `optional` with a value. Furthermore, this assignment
  172. //! operator only exists if the value held in the `optional` is
  173. //! MoveAssignable.
  174. constexpr optional& operator=(optional&&) = default;
  175. // 5.3.5, Observers
  176. //! Returns a pointer to the contained value, or a `nullptr` if the
  177. //! `optional` is empty.
  178. //!
  179. //!
  180. //! @note Overloads of this method are provided for both the `const`
  181. //! and the non-`const` cases.
  182. //!
  183. //!
  184. //! Example
  185. //! -------
  186. //! @include example/optional/value.cpp
  187. constexpr T* operator->();
  188. //! Extract the content of an `optional`, or fail at compile-time.
  189. //!
  190. //! If `*this` contains a value, that value is returned. Otherwise,
  191. //! a static assertion is triggered.
  192. //!
  193. //! @note
  194. //! Overloads of this method are provided for the cases where `*this`
  195. //! is a reference, a rvalue-reference and their `const` counterparts.
  196. //!
  197. //!
  198. //! Example
  199. //! -------
  200. //! @include example/optional/value.cpp
  201. constexpr T& value();
  202. //! Equivalent to `value()`, provided for convenience.
  203. //!
  204. //! @note
  205. //! Overloads of this method are provided for the cases where `*this`
  206. //! is a reference, a rvalue-reference and their `const` counterparts.
  207. //!
  208. //!
  209. //! Example
  210. //! -------
  211. //! @include example/optional/value.cpp
  212. constexpr T& operator*();
  213. //! Return the contents of an `optional`, with a fallback result.
  214. //!
  215. //! If `*this` contains a value, that value is returned. Otherwise,
  216. //! the default value provided is returned.
  217. //!
  218. //! @note
  219. //! Overloads of this method are provided for the cases where `*this`
  220. //! is a reference, a rvalue-reference and their `const` counterparts.
  221. //!
  222. //!
  223. //! @param default_
  224. //! The default value to return if `*this` does not contain a value.
  225. //!
  226. //!
  227. //! Example
  228. //! -------
  229. //! @include example/optional/value_or.cpp
  230. template <typename U>
  231. constexpr decltype(auto) value_or(U&& default_);
  232. //! Equivalent to `hana::chain`.
  233. template <typename ...T, typename F>
  234. friend constexpr auto operator|(optional<T...>, F);
  235. //! Equivalent to `hana::equal`
  236. template <typename X, typename Y>
  237. friend constexpr auto operator==(X&& x, Y&& y);
  238. //! Equivalent to `hana::not_equal`
  239. template <typename X, typename Y>
  240. friend constexpr auto operator!=(X&& x, Y&& y);
  241. //! Equivalent to `hana::less`
  242. template <typename X, typename Y>
  243. friend constexpr auto operator<(X&& x, Y&& y);
  244. //! Equivalent to `hana::greater`
  245. template <typename X, typename Y>
  246. friend constexpr auto operator>(X&& x, Y&& y);
  247. //! Equivalent to `hana::less_equal`
  248. template <typename X, typename Y>
  249. friend constexpr auto operator<=(X&& x, Y&& y);
  250. //! Equivalent to `hana::greater_equal`
  251. template <typename X, typename Y>
  252. friend constexpr auto operator>=(X&& x, Y&& y);
  253. };
  254. #else
  255. template <typename ...T>
  256. struct optional;
  257. #endif
  258. //! Tag representing a `hana::optional`.
  259. //! @relates hana::optional
  260. struct optional_tag { };
  261. //! Create an optional value.
  262. //! @relates hana::optional
  263. //!
  264. //! Specifically, `make<optional_tag>()` is equivalent to `nothing`, and
  265. //! `make<optional_tag>(x)` is equivalent to `just(x)`. This is provided
  266. //! for consistency with the other `make<...>` functions.
  267. //!
  268. //!
  269. //! Example
  270. //! -------
  271. //! @include example/optional/make.cpp
  272. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  273. template <>
  274. constexpr auto make<optional_tag> = []([auto&& x]) {
  275. return optional<std::decay<decltype(x)>::type>{forwarded(x)};
  276. };
  277. #endif
  278. //! Alias to `make<optional_tag>`; provided for convenience.
  279. //! @relates hana::optional
  280. //!
  281. //!
  282. //! Example
  283. //! -------
  284. //! @include example/optional/make.cpp
  285. BOOST_HANA_INLINE_VARIABLE constexpr auto make_optional = make<optional_tag>;
  286. //! Create an optional value containing `x`.
  287. //! @relates hana::optional
  288. //!
  289. //!
  290. //! Example
  291. //! -------
  292. //! @include example/optional/just.cpp
  293. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  294. constexpr auto just = [](auto&& x) {
  295. return optional<std::decay<decltype(x)>::type>{forwarded(x)};
  296. };
  297. #else
  298. struct make_just_t {
  299. template <typename T>
  300. constexpr auto operator()(T&&) const;
  301. };
  302. BOOST_HANA_INLINE_VARIABLE constexpr make_just_t just{};
  303. #endif
  304. //! An empty optional value.
  305. //! @relates hana::optional
  306. //!
  307. //!
  308. //! Example
  309. //! -------
  310. //! @include example/optional/nothing.cpp
  311. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  312. constexpr optional<> nothing{};
  313. #else
  314. template <>
  315. struct optional<> : detail::operators::adl<optional<>> {
  316. // 5.3.1, Constructors
  317. constexpr optional() = default;
  318. constexpr optional(optional const&) = default;
  319. constexpr optional(optional&&) = default;
  320. // 5.3.3, Assignment
  321. constexpr optional& operator=(optional const&) = default;
  322. constexpr optional& operator=(optional&&) = default;
  323. // 5.3.5, Observers
  324. constexpr decltype(nullptr) operator->() const { return nullptr; }
  325. template <typename ...dummy>
  326. constexpr auto value() const;
  327. template <typename ...dummy>
  328. constexpr auto operator*() const;
  329. template <typename U>
  330. constexpr U&& value_or(U&& u) const;
  331. };
  332. BOOST_HANA_INLINE_VARIABLE constexpr optional<> nothing{};
  333. #endif
  334. //! Apply a function to the contents of an optional, with a fallback
  335. //! result.
  336. //! @relates hana::optional
  337. //!
  338. //! Specifically, `maybe` takes a default value, a function and an
  339. //! optional value. If the optional value is `nothing`, the default
  340. //! value is returned. Otherwise, the function is applied to the
  341. //! content of the `just`.
  342. //!
  343. //!
  344. //! @param default_
  345. //! A default value returned if `m` is `nothing`.
  346. //!
  347. //! @param f
  348. //! A function called as `f(x)` if and only if `m` is an optional value
  349. //! of the form `just(x)`. In that case, the result returend by `maybe`
  350. //! is the result of `f`.
  351. //!
  352. //! @param m
  353. //! An optional value.
  354. //!
  355. //!
  356. //! Example
  357. //! -------
  358. //! @include example/optional/maybe.cpp
  359. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  360. constexpr auto maybe = [](auto&& default_, auto&& f, auto&& m) -> decltype(auto) {
  361. if (m is a just(x)) {
  362. return forwarded(f)(forwarded(x));
  363. else
  364. return forwarded(default_);
  365. }
  366. };
  367. #else
  368. struct maybe_t {
  369. template <typename Def, typename F, typename T>
  370. constexpr decltype(auto) operator()(Def&&, F&& f, optional<T> const& m) const
  371. { return static_cast<F&&>(f)(m.value_); }
  372. template <typename Def, typename F, typename T>
  373. constexpr decltype(auto) operator()(Def&&, F&& f, optional<T>& m) const
  374. { return static_cast<F&&>(f)(m.value_); }
  375. template <typename Def, typename F, typename T>
  376. constexpr decltype(auto) operator()(Def&&, F&& f, optional<T>&& m) const
  377. { return static_cast<F&&>(f)(static_cast<optional<T>&&>(m).value_); }
  378. template <typename Def, typename F>
  379. constexpr Def operator()(Def&& def, F&&, optional<> const&) const
  380. { return static_cast<Def&&>(def); }
  381. };
  382. BOOST_HANA_INLINE_VARIABLE constexpr maybe_t maybe{};
  383. #endif
  384. //! Calls a function if the call expression is well-formed.
  385. //! @relates hana::optional
  386. //!
  387. //! Given a function `f`, `sfinae` returns a new function applying `f`
  388. //! to its arguments and returning `just` the result if the call is
  389. //! well-formed, and `nothing` otherwise. In other words, `sfinae(f)(x...)`
  390. //! is `just(f(x...))` if that expression is well-formed, and `nothing`
  391. //! otherwise. Note, however, that it is possible for an expression
  392. //! `f(x...)` to be well-formed as far as SFINAE is concerned, but
  393. //! trying to actually compile `f(x...)` still fails. In this case,
  394. //! `sfinae` won't be able to detect it and a hard failure is likely
  395. //! to happen.
  396. //!
  397. //!
  398. //! @note
  399. //! The function given to `sfinae` must not return `void`, since
  400. //! `just(void)` does not make sense. A compilation error is
  401. //! triggered if the function returns void.
  402. //!
  403. //!
  404. //! Example
  405. //! -------
  406. //! @include example/optional/sfinae.cpp
  407. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  408. auto sfinae = [](auto&& f) {
  409. return [perfect-capture](auto&& ...x) {
  410. if (decltype(forwarded(f)(forwarded(x)...)) is well-formed)
  411. return just(forwarded(f)(forwarded(x)...));
  412. else
  413. return nothing;
  414. };
  415. };
  416. #else
  417. struct sfinae_t {
  418. template <typename F>
  419. constexpr decltype(auto) operator()(F&& f) const;
  420. };
  421. BOOST_HANA_INLINE_VARIABLE constexpr sfinae_t sfinae{};
  422. #endif
  423. //! Return whether an `optional` contains a value.
  424. //! @relates hana::optional
  425. //!
  426. //! Specifically, returns a compile-time true-valued `Logical` if `m` is
  427. //! of the form `just(x)` for some `x`, and a false-valued one otherwise.
  428. //!
  429. //!
  430. //! Example
  431. //! -------
  432. //! @include example/optional/is_just.cpp
  433. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  434. constexpr auto is_just = [](auto const& m) {
  435. return m is a just(x);
  436. };
  437. #else
  438. struct is_just_t {
  439. template <typename ...T>
  440. constexpr auto operator()(optional<T...> const&) const;
  441. };
  442. BOOST_HANA_INLINE_VARIABLE constexpr is_just_t is_just{};
  443. #endif
  444. //! Return whether an `optional` is empty.
  445. //! @relates hana::optional
  446. //!
  447. //! Specifically, returns a compile-time true-valued `Logical` if `m` is
  448. //! a `nothing`, and a false-valued one otherwise.
  449. //!
  450. //!
  451. //! Example
  452. //! -------
  453. //! @include example/optional/is_nothing.cpp
  454. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  455. constexpr auto is_nothing = [](auto const& m) {
  456. return m is a nothing;
  457. };
  458. #else
  459. struct is_nothing_t {
  460. template <typename ...T>
  461. constexpr auto operator()(optional<T...> const&) const;
  462. };
  463. BOOST_HANA_INLINE_VARIABLE constexpr is_nothing_t is_nothing{};
  464. #endif
  465. }} // end namespace boost::hana
  466. #endif // !BOOST_HANA_FWD_OPTIONAL_HPP