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