|
|
|||
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
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|