template<typename ... T>
struct boost::hana::optional< T >
Optional value whose optional-ness is known at compile-time.
An optional
either contains a value (represented as just(x)
), or it is empty (represented as nothing
). In essence, hana::optional
is pretty much like a boost::optional
or the upcoming std::optional
, except for the fact that whether a hana::optional
is empty or not is known at compile-time. This can be particularly useful for returning from a function that might fail, but whose reason for failing is not important. Of course, whether the function will fail has to be known at compile-time.
This is really an important difference between hana::optional
and std::optional
. Unlike std::optional<T>{}
and std::optional<T>{x}
who share the same type (std::optional<T>
), hana::just(x)
and hana::nothing
do not share the same type, since the state of the optional has to be known at compile-time. Hence, whether a hana::just
or a hana::nothing
will be returned from a function has to be known at compile-time for the return type of that function to be computable by the compiler. This makes hana::optional
well suited for static metaprogramming tasks, but very poor for anything dynamic.
- Note
- When you use a container, remember not to make assumptions about its representation, unless the documentation gives you those guarantees. More details in the tutorial.
Interoperation with <tt>type</tt>s
When a just
contains an object of type T
which is a type
, it has a nested ::type
alias equivalent to T::type
. nothing
, however, never has a nested ::type
alias. If t
is a type
, this allows decltype(just(t))
to be seen as a nullary metafunction equivalent to decltype(t)
. Along with the sfinae
function, this allows hana::optional
to interact seamlessly with SFINAE-friendly metafunctions. Example:
#include <type_traits>
#include <utility>
template <typename ...>
using void_t = void;
template <typename T, typename = void>
struct has_type : std::false_type { };
template <typename T>
struct has_type<T, void_t<typename T::type>>
: std::true_type
{ };
auto common_type_impl = hana::sfinae([](auto t, auto u) -> hana::type<
decltype(true ? hana::traits::declval(t) : hana::traits::declval(u))
> { return {}; });
template <typename T, typename U>
using common_type = decltype(common_type_impl(hana::type_c<T>, hana::type_c<U>));
common_type_impl(hana::type_c<int>, hana::type_c<float>)
==
hana::just(hana::type_c<float>)
);
static_assert(!has_type<common_type<int, int*>>{}, "");
static_assert(std::is_same<common_type<int, float>::type, float>{}, "");
int main() { }
Modeled concepts
Comparable
Two optional
s are equal if and only if they are both empty or they both contain a value and those values are equal.
static_assert(hana::just('x') == hana::just('x'), "");
static_assert(hana::just('x') != hana::just('y'), "");
int main() { }
Orderable
Optional values can be ordered by considering the value they are holding, if any. To handle the case of an empty optional value, we arbitrarily set nothing
as being less than any other just
. Hence, Example:
static_assert(hana::just(1) < hana::just(3), "");
static_assert(hana::just(3) > hana::just(2), "");
int main() { }
Functor
An optional value can be seen as a list containing either one element (just(x)
) or no elements at all (nothing
). As such, mapping a function over an optional value is equivalent to applying it to its value if there is one, and to nothing
otherwise: Example:
static_assert(hana::transform(hana::just(1),
hana::_ + 1) == hana::just(2),
"");
int main() { }
Applicative
First, a value can be made optional with lift<optional_tag>
, which is equivalent to just
. Second, one can feed an optional value to an optional function with ap
, which will return just(f(x))
if there is both a function and a value, and nothing
otherwise: A simple example:
constexpr char next(char c) { return c + 1; }
static_assert(hana::ap(hana::just(next), hana::just('x')) == hana::just('y'), "");
int main() { }
A more complex example:
template <char op>
constexpr auto function = hana::nothing;
template <>
BOOST_HANA_CONSTEXPR_LAMBDA auto function<'+'> = hana::just([](auto x, auto y) {
return x + y;
});
template <>
BOOST_HANA_CONSTEXPR_LAMBDA auto function<'-'> = hana::just([](auto x, auto y) {
return x - y;
});
template <char n>
constexpr
auto digit =
hana::if_(hana::bool_c<(n >=
'0' && n <=
'9')>,
hana::just(static_cast<int>(n - 48)),
hana::nothing
);
template <char x, char op, char y>
BOOST_HANA_CONSTEXPR_LAMBDA auto evaluate = hana::ap(function<op>, digit<x>, digit<y>);
int main() {
static_assert(hana::lift<hana::optional_tag>(123) == hana::just(123), "");
}
Monad
The Monad
model makes it easy to compose actions that might fail. One can feed an optional value if there is one into a function with chain
, which will return nothing
if there is no value. Finally, optional-optional values can have their redundant level of optionality removed with flatten
. Also note that the |
operator can be used in place of the chain
function. Example:
int main() {
BOOST_HANA_CONSTEXPR_LAMBDA auto inc = [](auto x) {
return hana::just(x + 1);
};
}
MonadPlus
The MonadPlus
model allows choosing the first valid value out of two optional values with concat
. If both optional values are nothing
s, concat
will return nothing
. Example:
static_assert(
hana::concat(hana::nothing, hana::just(
'x')) == hana::just(
'x'),
"");
static_assert(
hana::concat(hana::just(
'x'), hana::just(
'y')) == hana::just(
'x'),
"");
int main() { }
Foldable
Folding an optional value is equivalent to folding a list containing either no elements (for nothing
) or x
(for just(x)
). Example:
static_assert(hana::fold_right(hana::nothing, 1,
hana::plus) == 1,
"");
static_assert(hana::fold_right(hana::just(4), 1,
hana::plus) == 5,
"");
int main() { }
Searchable
Searching an optional value is equivalent to searching a list containing x
for just(x)
and an empty list for nothing
. Example:
auto odd = [](auto x) {
return x % hana::int_c<2> != hana::int_c<0>;
};
int main() { }
|
template<typename ... T, typename F > |
constexpr friend auto | operator| (optional< T... >, F) |
| Equivalent to hana::chain .
|
|
template<typename X , typename Y > |
constexpr friend auto | operator== (X &&x, Y &&y) |
| Equivalent to hana::equal
|
|
template<typename X , typename Y > |
constexpr friend auto | operator!= (X &&x, Y &&y) |
| Equivalent to hana::not_equal
|
|
template<typename X , typename Y > |
constexpr friend auto | operator< (X &&x, Y &&y) |
| Equivalent to hana::less
|
|
template<typename X , typename Y > |
constexpr friend auto | operator> (X &&x, Y &&y) |
| Equivalent to hana::greater
|
|
template<typename X , typename Y > |
constexpr friend auto | operator<= (X &&x, Y &&y) |
| Equivalent to hana::less_equal
|
|
template<typename X , typename Y > |
constexpr friend auto | operator>= (X &&x, Y &&y) |
| Equivalent to hana::greater_equal
|
|
|
constexpr | optional ()=default |
| Default-construct an optional . Only exists if the optional contains a value, and if that value is DefaultConstructible.
|
|
| optional (optional const &)=default |
| Copy-construct an optional . An empty optional may only be copy-constructed from another empty optional , and an optional with a value may only be copy-constructed from another optional with a value. Furthermore, this constructor only exists if the value held in the optional is CopyConstructible.
|
|
| optional (optional &&)=default |
| Move-construct an optional . An empty optional may only be move-constructed from another empty optional , and an optional with a value may only be move-constructed from another optional with a value. Furthermore, this constructor only exists if the value held in the optional is MoveConstructible.
|
|
constexpr | optional (T const &t) |
| Construct an optional holding a value of type T from another object of type T . The value is copy-constructed.
|
|
constexpr | optional (T &&t) |
| Construct an optional holding a value of type T from another object of type T . The value is move-constructed.
|
|
constexpr optional & | operator= (optional const &)=default |
| Copy-assign an optional . An empty optional may only be copy-assigned from another empty optional , and an optional with a value may only be copy-assigned from another optional with a value. Furthermore, this assignment operator only exists if the value held in the optional is CopyAssignable.
|
|
constexpr optional & | operator= (optional &&)=default |
| Move-assign an optional . An empty optional may only be move-assigned from another empty optional , and an optional with a value may only be move-assigned from another optional with a value. Furthermore, this assignment operator only exists if the value held in the optional is MoveAssignable.
|
|
constexpr T * | operator-> () |
| Returns a pointer to the contained value, or a nullptr if the optional is empty. More...
|
|
constexpr T & | value () |
| Extract the content of an optional , or fail at compile-time. More...
|
|
constexpr T & | operator* () |
| Equivalent to value() , provided for convenience. More...
|
|
template<typename U > |
constexpr decltype(auto) | value_or (U &&default_) |
| Return the contents of an optional , with a fallback result. More...
|
|