Boost.Hana  1.0.2
Your standard library for metaprogramming
boost::hana::optional< T > Struct Template Reference

Description

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.

Interoperation with types

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:

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <type_traits>
#include <utility>
namespace hana = boost::hana;
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) -> decltype(hana::type_c<
decltype(true ? hana::traits::declval(t) : hana::traits::declval(u))
>) { return {}; });
template <typename T, typename U>
using common_type2 = decltype(common_type_impl(hana::type_c<T>, hana::type_c<U>));
static_assert(!has_type<common_type2<int, int*>>{}, "");
static_assert(std::is_same<common_type2<int, float>::type, float>{}, "");
int main() { }

Modeled concepts

  1. Comparable
    Two optionals are equal if and only if they are both empty or they both contain a value and those values are equal.
    // Copyright Louis Dionne 2013-2016
    // Distributed under the Boost Software License, Version 1.0.
    // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
    namespace hana = boost::hana;
    BOOST_HANA_CONSTANT_CHECK(hana::nothing == hana::nothing);
    static_assert(hana::just('x') == hana::just('x'), "");
    static_assert(hana::just('x') != hana::just('y'), "");
    BOOST_HANA_CONSTANT_CHECK(hana::just('x') != hana::nothing);
    int main() { }
  2. 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,
    just(x) < just(y) if and only if x < y
    nothing < just(anything)
    Example:
    // Copyright Louis Dionne 2013-2016
    // Distributed under the Boost Software License, Version 1.0.
    // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
    namespace hana = boost::hana;
    BOOST_HANA_CONSTANT_CHECK(hana::nothing < hana::just(3));
    BOOST_HANA_CONSTANT_CHECK(hana::just(0) > hana::nothing);
    static_assert(hana::just(1) < hana::just(3), "");
    static_assert(hana::just(3) > hana::just(2), "");
    int main() { }
  3. 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:
    transform(just(x), f) == just(f(x))
    transform(nothing, f) == nothing
    Example:
    // Copyright Louis Dionne 2013-2016
    // Distributed under the Boost Software License, Version 1.0.
    // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
    namespace hana = boost::hana;
    BOOST_HANA_CONSTANT_CHECK(hana::transform(hana::nothing, hana::_ + 1) == hana::nothing);
    static_assert(hana::transform(hana::just(1), hana::_ + 1) == hana::just(2), "");
    int main() { }
  4. 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:
    ap(just(f), just(x)) == just(f(x))
    ap(nothing, just(x)) == nothing
    ap(just(f), nothing) == nothing
    ap(nothing, nothing) == nothing
    A simple example:
    // Copyright Louis Dionne 2013-2016
    // Distributed under the Boost Software License, Version 1.0.
    // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
    namespace hana = boost::hana;
    constexpr char next(char c) { return c + 1; }
    static_assert(hana::ap(hana::just(next), hana::just('x')) == hana::just('y'), "");
    BOOST_HANA_CONSTANT_CHECK(hana::ap(hana::nothing, hana::just('x')) == hana::nothing);
    BOOST_HANA_CONSTANT_CHECK(hana::ap(hana::just(next), hana::nothing) == hana::nothing);
    BOOST_HANA_CONSTANT_CHECK(hana::ap(hana::nothing, hana::nothing) == hana::nothing);
    int main() { }
    A more complex example:
    // Copyright Louis Dionne 2013-2016
    // Distributed under the Boost Software License, Version 1.0.
    // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
    namespace hana = boost::hana;
    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;
    });
    // and so on...
    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() {
    BOOST_HANA_CONSTEXPR_CHECK(evaluate<'1', '+', '2'> == hana::just(1 + 2));
    BOOST_HANA_CONSTANT_CHECK(evaluate<'?', '+', '2'> == hana::nothing);
    BOOST_HANA_CONSTANT_CHECK(evaluate<'1', '?', '2'> == hana::nothing);
    BOOST_HANA_CONSTANT_CHECK(evaluate<'1', '+', '?'> == hana::nothing);
    BOOST_HANA_CONSTANT_CHECK(evaluate<'?', '?', '?'> == hana::nothing);
    static_assert(hana::lift<hana::optional_tag>(123) == hana::just(123), "");
    }
  5. 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:
    // Copyright Louis Dionne 2013-2016
    // Distributed under the Boost Software License, Version 1.0.
    // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
    namespace hana = boost::hana;
    int main() {
    BOOST_HANA_CONSTEXPR_LAMBDA auto inc = [](auto x) {
    return hana::just(x + 1);
    };
    BOOST_HANA_CONSTEXPR_CHECK(hana::chain(hana::just(1), inc) == hana::just(2));
    BOOST_HANA_CONSTANT_CHECK(hana::chain(hana::nothing, inc) == hana::nothing);
    BOOST_HANA_CONSTEXPR_CHECK(hana::flatten(hana::just(hana::just(2))) == hana::just(2));
    }
  6. MonadPlus
    The MonadPlus model allows choosing the first valid value out of two optional values with concat. If both optional values are nothings, concat will return nothing. Example:
    // Copyright Louis Dionne 2013-2016
    // Distributed under the Boost Software License, Version 1.0.
    // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
    namespace hana = boost::hana;
    static_assert(hana::concat(hana::nothing, hana::just('x')) == hana::just('x'), "");
    BOOST_HANA_CONSTANT_CHECK(hana::concat(hana::nothing, hana::nothing) == hana::nothing);
    static_assert(hana::concat(hana::just('x'), hana::just('y')) == hana::just('x'), "");
    BOOST_HANA_CONSTANT_CHECK(hana::empty<hana::optional_tag>() == hana::nothing);
    int main() { }
  7. Foldable
    Folding an optional value is equivalent to folding a list containing either no elements (for nothing) or x (for just(x)). Example:
    // Copyright Louis Dionne 2013-2016
    // Distributed under the Boost Software License, Version 1.0.
    // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
    namespace hana = boost::hana;
    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() { }
  8. Searchable
    Searching an optional value is equivalent to searching a list containing x for just(x) and an empty list for nothing. Example:
    // Copyright Louis Dionne 2013-2016
    // Distributed under the Boost Software License, Version 1.0.
    // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
    namespace hana = boost::hana;
    auto odd = [](auto x) {
    return x % hana::int_c<2> != hana::int_c<0>;
    };
    BOOST_HANA_CONSTANT_CHECK(hana::find_if(hana::just(hana::int_c<3>), odd) == hana::just(hana::int_c<3>));
    BOOST_HANA_CONSTANT_CHECK(hana::find_if(hana::just(hana::int_c<2>), odd) == hana::nothing);
    BOOST_HANA_CONSTANT_CHECK(hana::find_if(hana::nothing, odd) == hana::nothing);
    BOOST_HANA_CONSTANT_CHECK(hana::all_of(hana::just(hana::int_c<3>), odd));
    int main() { }

Synopsis of associated functions

template<>
constexpr auto make< optional_tag >
 Create an optional value. More...
 
constexpr auto make_optional = make<optional_tag>
 Alias to make<optional_tag>; provided for convenience. More...
 
constexpr auto just
 Create an optional value containing x. More...
 
constexpr optional nothing {}
 An empty optional value. More...
 
constexpr auto maybe
 Apply a function to the contents of an optional, with a fallback result. More...
 
auto sfinae
 Calls a function if the call expression is well-formed. More...
 
constexpr auto is_just
 Return whether an optional contains a value. More...
 
constexpr auto is_nothing
 Return whether an optional is empty. More...
 

Friends

template<typename... T, typename F >
constexpr auto operator| (optional< T... >, F)
 Equivalent to hana::chain.
 
template<typename X , typename Y >
constexpr auto operator== (X &&x, Y &&y)
 Equivalent to hana::equal
 
template<typename X , typename Y >
constexpr auto operator!= (X &&x, Y &&y)
 Equivalent to hana::not_equal
 
template<typename X , typename Y >
constexpr auto operator< (X &&x, Y &&y)
 Equivalent to hana::less
 
template<typename X , typename Y >
constexpr auto operator> (X &&x, Y &&y)
 Equivalent to hana::greater
 
template<typename X , typename Y >
constexpr auto operator<= (X &&x, Y &&y)
 Equivalent to hana::less_equal
 
template<typename X , typename Y >
constexpr auto operator>= (X &&x, Y &&y)
 Equivalent to hana::greater_equal
 

Public Member Functions

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 optionaloperator= (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 optionaloperator= (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 >
decltype(auto) constexpr value_or (U &&default_)
 Return the contents of an optional, with a fallback result. More...
 

Associated functions

template<typename... T>
template<>
constexpr auto make< optional_tag >
related
Initial value:
= []([auto&& x]) {
return optional<std::decay<decltype(x)>::type>{forwarded(x)};
}

Create an optional value.

Specifically, make<optional_tag>() is equivalent to nothing, and make<optional_tag>(x) is equivalent to just(x). This is provided for consistency with the other make<...> functions.

Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
int main() {
constexpr auto x = hana::make<hana::optional_tag>();
BOOST_HANA_CONSTANT_CHECK(x == hana::make_optional());
BOOST_HANA_CONSTANT_CHECK(hana::is_nothing(x));
constexpr auto just_x = hana::make<hana::optional_tag>('x');
static_assert(just_x == hana::make_optional('x'), "");
BOOST_HANA_CONSTANT_CHECK(hana::is_just(just_x));
}
template<typename... T>
constexpr auto make_optional = make<optional_tag>
related

Alias to make<optional_tag>; provided for convenience.

Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
int main() {
constexpr auto x = hana::make<hana::optional_tag>();
BOOST_HANA_CONSTANT_CHECK(x == hana::make_optional());
BOOST_HANA_CONSTANT_CHECK(hana::is_nothing(x));
constexpr auto just_x = hana::make<hana::optional_tag>('x');
static_assert(just_x == hana::make_optional('x'), "");
BOOST_HANA_CONSTANT_CHECK(hana::is_just(just_x));
}
template<typename... T>
constexpr auto just
related
Initial value:
= [](auto&& x) {
return optional<std::decay<decltype(x)>::type>{forwarded(x)};
}

Create an optional value containing x.

Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
constexpr auto just_x = hana::just('x');
BOOST_HANA_CONSTANT_CHECK(hana::is_just(just_x));
int main() { }
template<typename... T>
constexpr optional nothing {}
related

An empty optional value.

Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
constexpr auto x = hana::nothing;
BOOST_HANA_CONSTANT_CHECK(hana::is_nothing(x));
int main() { }
template<typename... T>
constexpr auto maybe
related
Initial value:
= [](auto&& default_, auto&& f, auto&& m) -> decltype(auto) {
if (m is a just(x)) {
return forwarded(f)(forwarded(x));
else
return forwarded(default_);
}
}

Apply a function to the contents of an optional, with a fallback result.

Specifically, maybe takes a default value, a function and an optional value. If the optional value is nothing, the default value is returned. Otherwise, the function is applied to the content of the just.

Parameters
default_A default value returned if m is nothing.
fA function called as f(x) if and only if m is an optional value of the form just(x). In that case, the result returend by maybe is the result of f.
mAn optional value.

Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
static_assert(hana::maybe('x', hana::_ + 1, hana::just(1)) == 2, "");
static_assert(hana::maybe('x', hana::_ + 1, hana::nothing) == 'x', "");
int main() { }
template<typename... T>
auto sfinae
related
Initial value:
= [](auto&& f) {
return [perfect-capture](auto&& ...x) {
if (decltype(forwarded(f)(forwarded(x)...)) is well-formed)
return just(forwarded(f)(forwarded(x)...));
else
return nothing;
};
}

Calls a function if the call expression is well-formed.

Given a function f, sfinae returns a new function applying f to its arguments and returning just the result if the call is well-formed, and nothing otherwise. In other words, sfinae(f)(x...) is just(f(x...)) if that expression is well-formed, and nothing otherwise. Note, however, that it is possible for an expression f(x...) to be well-formed as far as SFINAE is concerned, but trying to actually compile f(x...) still fails. In this case, sfinae won't be able to detect it and a hard failure is likely to happen.

Note
The function given to sfinae must not return void, since just(void) does not make sense. A compilation error is triggered if the function returns void.

Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
int main() {
BOOST_HANA_CONSTEXPR_LAMBDA auto incr = [](auto x) -> decltype(x + 1) {
return x + 1;
};
BOOST_HANA_CONSTEXPR_CHECK(hana::sfinae(incr)(1) == hana::just(2));
struct invalid { };
BOOST_HANA_CONSTANT_CHECK(hana::sfinae(incr)(invalid{}) == hana::nothing);
}
template<typename... T>
constexpr auto is_just
related
Initial value:
= [](auto const& m) {
return m is a just(x);
}

Return whether an optional contains a value.

Specifically, returns a compile-time true-valued Logical if m is of the form just(x) for some x, and a false-valued one otherwise.

Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
BOOST_HANA_CONSTANT_CHECK( hana::is_just(hana::just('x')));
BOOST_HANA_CONSTANT_CHECK( hana::is_just(hana::just(hana::nothing)));
BOOST_HANA_CONSTANT_CHECK(!hana::is_just(hana::nothing));
int main() { }
template<typename... T>
constexpr auto is_nothing
related
Initial value:
= [](auto const& m) {
return m is a nothing;
}

Return whether an optional is empty.

Specifically, returns a compile-time true-valued Logical if m is a nothing, and a false-valued one otherwise.

Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
BOOST_HANA_CONSTANT_CHECK( hana::is_nothing(hana::nothing));
BOOST_HANA_CONSTANT_CHECK(!hana::is_nothing(hana::just('x')));
BOOST_HANA_CONSTANT_CHECK(!hana::is_nothing(hana::just(hana::nothing)));
int main() { }

Member Function Documentation

template<typename... T>
constexpr T* boost::hana::optional< T >::operator-> ( )

Returns a pointer to the contained value, or a nullptr if the optional is empty.

Note
Overloads of this method are provided for both the const and the non-const cases.

Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <string>
namespace hana = boost::hana;
int main() {
static_assert(hana::just('x').value() == 'x', "");
BOOST_HANA_CONSTANT_CHECK(*hana::just(hana::type_c<int>) == hana::type_c<int>);
BOOST_HANA_RUNTIME_CHECK(hana::just(std::string{"abcd"})->size() == 4);
// hana::nothing.value(); // compile-time error
}
template<typename... T>
constexpr T& boost::hana::optional< T >::value ( )

Extract the content of an optional, or fail at compile-time.

If *this contains a value, that value is returned. Otherwise, a static assertion is triggered.

Note
Overloads of this method are provided for the cases where *this is a reference, a rvalue-reference and their const counterparts.

Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <string>
namespace hana = boost::hana;
int main() {
static_assert(hana::just('x').value() == 'x', "");
BOOST_HANA_CONSTANT_CHECK(*hana::just(hana::type_c<int>) == hana::type_c<int>);
BOOST_HANA_RUNTIME_CHECK(hana::just(std::string{"abcd"})->size() == 4);
// hana::nothing.value(); // compile-time error
}
template<typename... T>
constexpr T& boost::hana::optional< T >::operator* ( )

Equivalent to value(), provided for convenience.

Note
Overloads of this method are provided for the cases where *this is a reference, a rvalue-reference and their const counterparts.

Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#include <string>
namespace hana = boost::hana;
int main() {
static_assert(hana::just('x').value() == 'x', "");
BOOST_HANA_CONSTANT_CHECK(*hana::just(hana::type_c<int>) == hana::type_c<int>);
BOOST_HANA_RUNTIME_CHECK(hana::just(std::string{"abcd"})->size() == 4);
// hana::nothing.value(); // compile-time error
}
template<typename... T>
template<typename U >
decltype(auto) constexpr boost::hana::optional< T >::value_or ( U &&  default_)

Return the contents of an optional, with a fallback result.

If *this contains a value, that value is returned. Otherwise, the default value provided is returned.

Note
Overloads of this method are provided for the cases where *this is a reference, a rvalue-reference and their const counterparts.
Parameters
default_The default value to return if *this does not contain a value.

Example

// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
namespace hana = boost::hana;
static_assert(hana::just(1).value_or('x') == 1, "");
static_assert(hana::nothing.value_or('x') == 'x', "");
int main() { }