Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 09:53:04

0001 /*!
0002 @file
0003 Forward declares `boost::hana::optional`.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Distributed under the Boost Software License, Version 1.0.
0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
0008  */
0009 
0010 #ifndef BOOST_HANA_FWD_OPTIONAL_HPP
0011 #define BOOST_HANA_FWD_OPTIONAL_HPP
0012 
0013 #include <boost/hana/config.hpp>
0014 #include <boost/hana/detail/operators/adl.hpp>
0015 #include <boost/hana/fwd/core/make.hpp>
0016 
0017 
0018 namespace boost { namespace hana {
0019     //! @ingroup group-datatypes
0020     //! Optional value whose optional-ness is known at compile-time.
0021     //!
0022     //! An `optional` either contains a value (represented as `just(x)`), or
0023     //! it is empty (represented as `nothing`). In essence, `hana::optional`
0024     //! is pretty much like a `boost::optional` or the upcoming `std::optional`,
0025     //! except for the fact that whether a `hana::optional` is empty or not is
0026     //! known at compile-time. This can be particularly useful for returning
0027     //! from a function that might fail, but whose reason for failing is not
0028     //! important. Of course, whether the function will fail has to be known
0029     //! at compile-time.
0030     //!
0031     //! This is really an important difference between `hana::optional` and
0032     //! `std::optional`. Unlike `std::optional<T>{}` and `std::optional<T>{x}`
0033     //! who share the same type (`std::optional<T>`), `hana::just(x)` and
0034     //! `hana::nothing` do not share the same type, since the state of the
0035     //! optional has to be known at compile-time. Hence, whether a `hana::just`
0036     //! or a `hana::nothing` will be returned from a function has to be known
0037     //! at compile-time for the return type of that function to be computable
0038     //! by the compiler. This makes `hana::optional` well suited for static
0039     //! metaprogramming tasks, but very poor for anything dynamic.
0040     //!
0041     //! @note
0042     //! When you use a container, remember not to make assumptions about its
0043     //! representation, unless the documentation gives you those guarantees.
0044     //! More details [in the tutorial](@ref tutorial-containers-types).
0045     //!
0046     //!
0047     //! Interoperation with `type`s
0048     //! ---------------------------
0049     //! When a `just` contains an object of type `T` which is a `type`,
0050     //! it has a nested `::%type` alias equivalent to `T::%type`. `nothing`,
0051     //! however, never has a nested `::%type` alias. If `t` is a `type`,
0052     //! this allows `decltype(just(t))` to be seen as a nullary metafunction
0053     //! equivalent to `decltype(t)`. Along with the `sfinae` function,
0054     //! this allows `hana::optional` to interact seamlessly with
0055     //! SFINAE-friendly metafunctions.
0056     //! Example:
0057     //! @include example/optional/sfinae_friendly_metafunctions.cpp
0058     //!
0059     //!
0060     //! Modeled concepts
0061     //! ----------------
0062     //! 1. `Comparable`\n
0063     //! Two `optional`s are equal if and only if they are both empty or they
0064     //! both contain a value and those values are equal.
0065     //! @include example/optional/comparable.cpp
0066     //!
0067     //! 2. `Orderable`\n
0068     //! Optional values can be ordered by considering the value they are
0069     //! holding, if any. To handle the case of an empty optional value, we
0070     //! arbitrarily set `nothing` as being less than any other `just`. Hence,
0071     //! @code
0072     //!     just(x) < just(y) if and only if x < y
0073     //!     nothing < just(anything)
0074     //! @endcode
0075     //! Example:
0076     //! @include example/optional/orderable.cpp
0077     //!
0078     //! 3. `Functor`\n
0079     //! An optional value can be seen as a list containing either one element
0080     //! (`just(x)`) or no elements at all (`nothing`). As such, mapping
0081     //! a function over an optional value is equivalent to applying it to
0082     //! its value if there is one, and to `nothing` otherwise:
0083     //! @code
0084     //!     transform(just(x), f) == just(f(x))
0085     //!     transform(nothing, f) == nothing
0086     //! @endcode
0087     //! Example:
0088     //! @include example/optional/functor.cpp
0089     //!
0090     //! 4. `Applicative`\n
0091     //! First, a value can be made optional with `lift<optional_tag>`, which
0092     //! is equivalent to `just`. Second, one can feed an optional value to an
0093     //! optional function with `ap`, which will return `just(f(x))` if there
0094     //! is both a function _and_ a value, and `nothing` otherwise:
0095     //! @code
0096     //!     ap(just(f), just(x)) == just(f(x))
0097     //!     ap(nothing, just(x)) == nothing
0098     //!     ap(just(f), nothing) == nothing
0099     //!     ap(nothing, nothing) == nothing
0100     //! @endcode
0101     //! A simple example:
0102     //! @include example/optional/applicative.cpp
0103     //! A more complex example:
0104     //! @include example/optional/applicative.complex.cpp
0105     //!
0106     //! 5. `Monad`\n
0107     //! The `Monad` model makes it easy to compose actions that might fail.
0108     //! One can feed an optional value if there is one into a function with
0109     //! `chain`, which will return `nothing` if there is no value. Finally,
0110     //! optional-optional values can have their redundant level of optionality
0111     //! removed with `flatten`. Also note that the `|` operator can be used in
0112     //! place of the `chain` function.
0113     //! Example:
0114     //! @include example/optional/monad.cpp
0115     //!
0116     //! 6. `MonadPlus`\n
0117     //! The `MonadPlus` model allows choosing the first valid value out of
0118     //! two optional values with `concat`. If both optional values are
0119     //! `nothing`s, `concat` will return `nothing`.
0120     //! Example:
0121     //! @include example/optional/monad_plus.cpp
0122     //!
0123     //! 7. `Foldable`\n
0124     //! Folding an optional value is equivalent to folding a list containing
0125     //! either no elements (for `nothing`) or `x` (for `just(x)`).
0126     //! Example:
0127     //! @include example/optional/foldable.cpp
0128     //!
0129     //! 8. `Searchable`\n
0130     //! Searching an optional value is equivalent to searching a list
0131     //! containing `x` for `just(x)` and an empty list for `nothing`.
0132     //! Example:
0133     //! @include example/optional/searchable.cpp
0134 #ifdef BOOST_HANA_DOXYGEN_INVOKED
0135     template <typename ...T>
0136     struct optional {
0137         // 5.3.1, Constructors
0138 
0139         //! Default-construct an `optional`. Only exists if the optional
0140         //! contains a value, and if that value is DefaultConstructible.
0141         constexpr optional() = default;
0142 
0143         //! Copy-construct an `optional`.
0144         //! An empty optional may only be copy-constructed from another
0145         //! empty `optional`, and an `optional` with a value may only be
0146         //! copy-constructed from another `optional` with a value.
0147         //! Furthermore, this constructor only exists if the value
0148         //! held in the `optional` is CopyConstructible.
0149         optional(optional const&) = default;
0150 
0151         //! Move-construct an `optional`.
0152         //! An empty optional may only be move-constructed from another
0153         //! empty `optional`, and an `optional` with a value may only be
0154         //! move-constructed from another `optional` with a value.
0155         //! Furthermore, this constructor only exists if the value
0156         //! held in the `optional` is MoveConstructible.
0157         optional(optional&&) = default;
0158 
0159         //! Construct an `optional` holding a value of type `T` from another
0160         //! object of type `T`. The value is copy-constructed.
0161         constexpr optional(T const& t)
0162             : value_(t)
0163         { }
0164 
0165         //! Construct an `optional` holding a value of type `T` from another
0166         //! object of type `T`. The value is move-constructed.
0167         constexpr optional(T&& t)
0168             : value_(static_cast<T&&>(t))
0169         { }
0170 
0171         // 5.3.3, Assignment
0172 
0173         //! Copy-assign an `optional`.
0174         //! An empty optional may only be copy-assigned from another empty
0175         //! `optional`, and an `optional` with a value may only be copy-assigned
0176         //! from another `optional` with a value. Furthermore, this assignment
0177         //! operator only exists if the value held in the `optional` is
0178         //! CopyAssignable.
0179         constexpr optional& operator=(optional const&) = default;
0180 
0181         //! Move-assign an `optional`.
0182         //! An empty optional may only be move-assigned from another empty
0183         //! `optional`, and an `optional` with a value may only be move-assigned
0184         //! from another `optional` with a value. Furthermore, this assignment
0185         //! operator only exists if the value held in the `optional` is
0186         //! MoveAssignable.
0187         constexpr optional& operator=(optional&&) = default;
0188 
0189         // 5.3.5, Observers
0190 
0191         //! Returns a pointer to the contained value, or a `nullptr` if the
0192         //! `optional` is empty.
0193         //!
0194         //!
0195         //! @note Overloads of this method are provided for both the `const`
0196         //! and the non-`const` cases.
0197         //!
0198         //!
0199         //! Example
0200         //! -------
0201         //! @include example/optional/value.cpp
0202         constexpr T* operator->();
0203 
0204         //! Extract the content of an `optional`, or fail at compile-time.
0205         //!
0206         //! If `*this` contains a value, that value is returned. Otherwise,
0207         //! a static assertion is triggered.
0208         //!
0209         //! @note
0210         //! Overloads of this method are provided for the cases where `*this`
0211         //! is a reference, a rvalue-reference and their `const` counterparts.
0212         //!
0213         //!
0214         //! Example
0215         //! -------
0216         //! @include example/optional/value.cpp
0217         constexpr T& value();
0218 
0219         //! Equivalent to `value()`, provided for convenience.
0220         //!
0221         //! @note
0222         //! Overloads of this method are provided for the cases where `*this`
0223         //! is a reference, a rvalue-reference and their `const` counterparts.
0224         //!
0225         //!
0226         //! Example
0227         //! -------
0228         //! @include example/optional/value.cpp
0229         constexpr T& operator*();
0230 
0231         //! Return the contents of an `optional`, with a fallback result.
0232         //!
0233         //! If `*this` contains a value, that value is returned. Otherwise,
0234         //! the default value provided is returned.
0235         //!
0236         //! @note
0237         //! Overloads of this method are provided for the cases where `*this`
0238         //! is a reference, a rvalue-reference and their `const` counterparts.
0239         //!
0240         //!
0241         //! @param default_
0242         //! The default value to return if `*this` does not contain a value.
0243         //!
0244         //!
0245         //! Example
0246         //! -------
0247         //! @include example/optional/value_or.cpp
0248         template <typename U>
0249         constexpr decltype(auto) value_or(U&& default_);
0250 
0251         //! Equivalent to `hana::chain`.
0252         template <typename ...T, typename F>
0253         friend constexpr auto operator|(optional<T...>, F);
0254 
0255         //! Equivalent to `hana::equal`
0256         template <typename X, typename Y>
0257         friend constexpr auto operator==(X&& x, Y&& y);
0258 
0259         //! Equivalent to `hana::not_equal`
0260         template <typename X, typename Y>
0261         friend constexpr auto operator!=(X&& x, Y&& y);
0262 
0263         //! Equivalent to `hana::less`
0264         template <typename X, typename Y>
0265         friend constexpr auto operator<(X&& x, Y&& y);
0266 
0267         //! Equivalent to `hana::greater`
0268         template <typename X, typename Y>
0269         friend constexpr auto operator>(X&& x, Y&& y);
0270 
0271         //! Equivalent to `hana::less_equal`
0272         template <typename X, typename Y>
0273         friend constexpr auto operator<=(X&& x, Y&& y);
0274 
0275         //! Equivalent to `hana::greater_equal`
0276         template <typename X, typename Y>
0277         friend constexpr auto operator>=(X&& x, Y&& y);
0278     };
0279 #else
0280     template <typename ...T>
0281     struct optional;
0282 #endif
0283 
0284     //! Tag representing a `hana::optional`.
0285     //! @relates hana::optional
0286     struct optional_tag { };
0287 
0288     //! Create an optional value.
0289     //! @relates hana::optional
0290     //!
0291     //! Specifically, `make<optional_tag>()` is equivalent to `nothing`, and
0292     //! `make<optional_tag>(x)` is equivalent to `just(x)`. This is provided
0293     //! for consistency with the other `make<...>` functions.
0294     //!
0295     //!
0296     //! Example
0297     //! -------
0298     //! @include example/optional/make.cpp
0299 #ifdef BOOST_HANA_DOXYGEN_INVOKED
0300     template <>
0301     constexpr auto make<optional_tag> = []([auto&& x]) {
0302         return optional<std::decay<decltype(x)>::type>{forwarded(x)};
0303     };
0304 #endif
0305 
0306     //! Alias to `make<optional_tag>`; provided for convenience.
0307     //! @relates hana::optional
0308     //!
0309     //!
0310     //! Example
0311     //! -------
0312     //! @include example/optional/make.cpp
0313     BOOST_HANA_INLINE_VARIABLE constexpr auto make_optional = make<optional_tag>;
0314 
0315     //! Create an optional value containing `x`.
0316     //! @relates hana::optional
0317     //!
0318     //!
0319     //! Example
0320     //! -------
0321     //! @include example/optional/just.cpp
0322 #ifdef BOOST_HANA_DOXYGEN_INVOKED
0323     constexpr auto just = [](auto&& x) {
0324         return optional<std::decay<decltype(x)>::type>{forwarded(x)};
0325     };
0326 #else
0327     struct make_just_t {
0328         template <typename T>
0329         constexpr auto operator()(T&&) const;
0330     };
0331 
0332     BOOST_HANA_INLINE_VARIABLE constexpr make_just_t just{};
0333 #endif
0334 
0335     //! An empty optional value.
0336     //! @relates hana::optional
0337     //!
0338     //!
0339     //! Example
0340     //! -------
0341     //! @include example/optional/nothing.cpp
0342 #ifdef BOOST_HANA_DOXYGEN_INVOKED
0343     constexpr optional<> nothing{};
0344 #else
0345     template <>
0346     struct optional<> : detail::operators::adl<optional<>> {
0347         // 5.3.1, Constructors
0348         constexpr optional() = default;
0349         constexpr optional(optional const&) = default;
0350         constexpr optional(optional&&) = default;
0351 
0352         // 5.3.3, Assignment
0353         constexpr optional& operator=(optional const&) = default;
0354         constexpr optional& operator=(optional&&) = default;
0355 
0356         // 5.3.5, Observers
0357         constexpr decltype(nullptr) operator->() const { return nullptr; }
0358 
0359         template <typename ...dummy>
0360         constexpr auto value() const;
0361 
0362         template <typename ...dummy>
0363         constexpr auto operator*() const;
0364 
0365         template <typename U>
0366         constexpr U&& value_or(U&& u) const;
0367     };
0368 
0369     BOOST_HANA_INLINE_VARIABLE constexpr optional<> nothing{};
0370 #endif
0371 
0372     //! Apply a function to the contents of an optional, with a fallback
0373     //! result.
0374     //! @relates hana::optional
0375     //!
0376     //! Specifically, `maybe` takes a default value, a function and an
0377     //! optional value. If the optional value is `nothing`, the default
0378     //! value is returned. Otherwise, the function is applied to the
0379     //! content of the `just`.
0380     //!
0381     //!
0382     //! @param default_
0383     //! A default value returned if `m` is `nothing`.
0384     //!
0385     //! @param f
0386     //! A function called as `f(x)` if and only if `m` is an optional value
0387     //! of the form `just(x)`. In that case, the result returend by `maybe`
0388     //! is the result of `f`.
0389     //!
0390     //! @param m
0391     //! An optional value.
0392     //!
0393     //!
0394     //! Example
0395     //! -------
0396     //! @include example/optional/maybe.cpp
0397 #ifdef BOOST_HANA_DOXYGEN_INVOKED
0398     constexpr auto maybe = [](auto&& default_, auto&& f, auto&& m) -> decltype(auto) {
0399         if (m is a just(x)) {
0400             return forwarded(f)(forwarded(x));
0401         else
0402             return forwarded(default_);
0403         }
0404     };
0405 #else
0406     struct maybe_t {
0407         template <typename Def, typename F, typename T>
0408         constexpr decltype(auto) operator()(Def&&, F&& f, optional<T> const& m) const
0409         { return static_cast<F&&>(f)(m.value_); }
0410 
0411         template <typename Def, typename F, typename T>
0412         constexpr decltype(auto) operator()(Def&&, F&& f, optional<T>& m) const
0413         { return static_cast<F&&>(f)(m.value_); }
0414 
0415         template <typename Def, typename F, typename T>
0416         constexpr decltype(auto) operator()(Def&&, F&& f, optional<T>&& m) const
0417         { return static_cast<F&&>(f)(static_cast<optional<T>&&>(m).value_); }
0418 
0419         template <typename Def, typename F>
0420         constexpr Def operator()(Def&& def, F&&, optional<> const&) const
0421         { return static_cast<Def&&>(def); }
0422     };
0423 
0424     BOOST_HANA_INLINE_VARIABLE constexpr maybe_t maybe{};
0425 #endif
0426 
0427     //! Calls a function if the call expression is well-formed.
0428     //! @relates hana::optional
0429     //!
0430     //! Given a function `f`, `sfinae` returns a new function applying `f`
0431     //! to its arguments and returning `just` the result if the call is
0432     //! well-formed, and `nothing` otherwise. In other words, `sfinae(f)(x...)`
0433     //! is `just(f(x...))` if that expression is well-formed, and `nothing`
0434     //! otherwise. Note, however, that it is possible for an expression
0435     //! `f(x...)` to be well-formed as far as SFINAE is concerned, but
0436     //! trying to actually compile `f(x...)` still fails. In this case,
0437     //! `sfinae` won't be able to detect it and a hard failure is likely
0438     //! to happen.
0439     //!
0440     //!
0441     //! @note
0442     //! The function given to `sfinae` must not return `void`, since
0443     //! `just(void)` does not make sense. A compilation error is
0444     //! triggered if the function returns void.
0445     //!
0446     //!
0447     //! Example
0448     //! -------
0449     //! @include example/optional/sfinae.cpp
0450 #ifdef BOOST_HANA_DOXYGEN_INVOKED
0451     auto sfinae = [](auto&& f) {
0452         return [perfect-capture](auto&& ...x) {
0453             if (decltype(forwarded(f)(forwarded(x)...)) is well-formed)
0454                 return just(forwarded(f)(forwarded(x)...));
0455             else
0456                 return nothing;
0457         };
0458     };
0459 #else
0460     struct sfinae_t {
0461         template <typename F>
0462         constexpr decltype(auto) operator()(F&& f) const;
0463     };
0464 
0465     BOOST_HANA_INLINE_VARIABLE constexpr sfinae_t sfinae{};
0466 #endif
0467 
0468     //! Return whether an `optional` contains a value.
0469     //! @relates hana::optional
0470     //!
0471     //! Specifically, returns a compile-time true-valued `Logical` if `m` is
0472     //! of the form `just(x)` for some `x`, and a false-valued one otherwise.
0473     //!
0474     //!
0475     //! Example
0476     //! -------
0477     //! @include example/optional/is_just.cpp
0478 #ifdef BOOST_HANA_DOXYGEN_INVOKED
0479     constexpr auto is_just = [](auto const& m) {
0480         return m is a just(x);
0481     };
0482 #else
0483     struct is_just_t {
0484         template <typename ...T>
0485         constexpr auto operator()(optional<T...> const&) const;
0486     };
0487 
0488     BOOST_HANA_INLINE_VARIABLE constexpr is_just_t is_just{};
0489 #endif
0490 
0491     //! Return whether an `optional` is empty.
0492     //! @relates hana::optional
0493     //!
0494     //! Specifically, returns a compile-time true-valued `Logical` if `m` is
0495     //! a `nothing`, and a false-valued one otherwise.
0496     //!
0497     //!
0498     //! Example
0499     //! -------
0500     //! @include example/optional/is_nothing.cpp
0501 #ifdef BOOST_HANA_DOXYGEN_INVOKED
0502     constexpr auto is_nothing = [](auto const& m) {
0503         return m is a nothing;
0504     };
0505 #else
0506     struct is_nothing_t {
0507         template <typename ...T>
0508         constexpr auto operator()(optional<T...> const&) const;
0509     };
0510 
0511     BOOST_HANA_INLINE_VARIABLE constexpr is_nothing_t is_nothing{};
0512 #endif
0513 }} // end namespace boost::hana
0514 
0515 #endif // !BOOST_HANA_FWD_OPTIONAL_HPP