Boost.Hana  1.5.0
Your standard library for metaprogramming
Core

Description

Core utilities of the library.

Classes

struct  boost::hana::common< T, U, enabler >
 Metafunction returning the common data type between two data types. More...
 
struct  boost::hana::has_common< T, U, typename >
 Metafunction returning whether two data types share a common data type. More...
 
struct  boost::hana::default_
 Mark a tag-dispatched method implementation as a default implementation. More...
 
struct  boost::hana::is_default< Method, typename >
 Returns whether a tag-dispatched method implementation is a default implementation. More...
 
struct  boost::hana::tag_of< T, enabler >
 Metafunction returning the tag associated to T. More...
 
struct  boost::hana::is_convertible< From, To, typename >
 Returns whether there is a Hana-conversion from a data type to another. More...
 
struct  boost::hana::embedding< bool >
 Marks a conversion between data types as being an embedding. More...
 
struct  boost::hana::is_embedded< From, To, typename >
 Returns whether a data type can be embedded into another data type. More...
 
struct  boost::hana::when< condition >
 Enable a partial specialization only if a boolean condition is true. More...
 

Typedefs

template<typename T , typename U >
using boost::hana::common_t = typename common< T, U >::type
 Alias to common<T, U>::type, provided for convenience. More...
 
template<typename T >
using boost::hana::tag_of_t = typename hana::tag_of< T >::type
 Alias to tag_of<T>::type, provided for convenience. More...
 
template<typename... >
using boost::hana::when_valid = when< true >
 Variant of when allowing specializations to be enabled only if an expression is well-formed. More...
 

Variables

template<typename Tag , typename optional_T >
constexpr auto boost::hana::is_a = see-documentation
 Returns whether the tag of an object matches a given tag. More...
 
template<typename Tag , typename... T>
constexpr auto boost::hana::is_an = is_a<Tag, T...>
 Equivalent to is_a; provided for consistency with the rules of the English language.
 
template<typename Tag >
constexpr auto boost::hana::make
 Create an object of the given tag with the given arguments. More...
 
template<typename To >
constexpr auto boost::hana::to
 Converts an object from one data type to another. More...
 

Typedef Documentation

template<typename T , typename U >
using boost::hana::common_t = typedef typename common<T, U>::type

#include <boost/hana/fwd/core/common.hpp>

Alias to common<T, U>::type, provided for convenience.

Example

// Copyright Louis Dionne 2013-2017
// 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>
namespace hana = boost::hana;
static_assert(std::is_same<
hana::common_t<int, float>,
hana::common<int, float>::type
>{}, "");
int main() { }
template<typename T >
using boost::hana::tag_of_t = typedef typename hana::tag_of<T>::type

#include <boost/hana/fwd/core/tag_of.hpp>

Alias to tag_of<T>::type, provided for convenience.

Example

// Copyright Louis Dionne 2013-2017
// 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>
namespace hana = boost::hana;
struct PersonTag;
struct Person { using hana_tag = PersonTag; };
static_assert(std::is_same<hana::tag_of_t<Person>, PersonTag>{}, "");
int main() { }
template<typename... >
using boost::hana::when_valid = typedef when<true>

#include <boost/hana/fwd/core/when.hpp>

Variant of when allowing specializations to be enabled only if an expression is well-formed.

when_valid<...> is always equivalent to when<true>. However, when used inside a partial specialization, SFINAE will cause the partial specialization to be ignored when the expression is ill-formed.

Example

// Copyright Louis Dionne 2013-2017
// 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>
namespace hana = boost::hana;
template <typename T, typename = hana::when<true>>
struct base_template;
template <typename T>
struct base_template<T, hana::when_valid<typename T::value_type>> {
// something useful...
};
int main() { }
Bug:
Using when_valid seems to trigger ambiguous partial specializations on GCC.

Variable Documentation

template<typename Tag , typename optional_T >
constexpr auto boost::hana::is_a = see-documentation

#include <boost/hana/fwd/core/is_a.hpp>

Returns whether the tag of an object matches a given tag.

Given a tag Tag and a C++ type T, is_a<Tag, T> is a compile-time Logical representing whether the tag of T is exactly Tag. In other words, it is equivalent to

std::is_same<Tag, tag_of<T>::type>

For convenience, an alternate syntax is provided for using is_a. Specifically, is_a<Tag> is a function object returning whether the argument it is passed has the given tag. In other words,

is_a<Tag>(x) == is_a<Tag, decltype(x)>

Example

// Copyright Louis Dionne 2013-2017
// 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::is_a<hana::tuple_tag, decltype(hana::make_tuple(1, '2', 3.3))>, "");
static_assert(!hana::is_a<hana::tuple_tag, void>, "");
static_assert(hana::is_an<hana::integral_constant_tag<int>>(hana::int_c<10>), "");
int main() { }
template<typename Tag >
constexpr auto boost::hana::make

#include <boost/hana/fwd/core/make.hpp>

Initial value:
= [](auto&& ...x) -> decltype(auto) {
return tag-dispatched;
}

Create an object of the given tag with the given arguments.

This function serves the same purpose as constructors in usual C++. However, instead of creating an object of a specific C++ type, it creates an object of a specific tag, regardless of the C++ type of that object.

This function is actually a variable template, so make<T> can be passed around as a function object creating an object of tag T. Also, it uses tag-dispatching so this is how it should be customized for user-defined tags.

Finally, the default implementation of make is equivalent to calling the constructor of the given tag with the corresponding arguments. In other words, by default,

make<T>(args...) == T(args...)

Note that the arguments are perfectly forwarded and the form of construction which is used is exactly as documented, i.e. T(args...). However, if T(args...) is not a valid expression, a compilation error is triggered. This default behavior is useful because it makes foreign C++ types that have no notion of tag constructible with make out-of-the-box, since their tag is exactly themselves.

Example

// Copyright Louis Dionne 2013-2017
// 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() {
hana::tuple<int, char, double, std::string> ts{1, '2', 3.3, "abcd"};
BOOST_HANA_RUNTIME_CHECK(ts == hana::make_tuple(1, '2', 3.3, std::string{"abcd"}));
// std::string has no notion of tag, but it still works with make<>
std::string foo{"foo"};
BOOST_HANA_RUNTIME_CHECK(hana::make<std::string>("foo") == foo);
}
template<typename To >
constexpr auto boost::hana::to

#include <boost/hana/fwd/core/to.hpp>

Initial value:
= [](auto&& x) -> decltype(auto) {
return tag-dispatched;
}

Converts an object from one data type to another.

to is a natural extension of the static_cast language construct to data types. Given a destination data type To and an object x, to creates a new object of data type To from x. Note, however, that to is not required to actually create a new object, and may return a reference to the original object (for example when trying to convert an object to its own data type).

As a natural extension to static_cast, to provides a default behavior. For the purpose of what follows, let To be the destination data type and From be the data type of x, i.e. the source data type. Then, to has the following default behavior:

  1. If the To and From data types are the same, then the object is forwarded as-is.
  2. Otherwise, if From is convertible to To using static_cast, x is converted to From using static_cast.
  3. Otherwise, calling to<From>(x) triggers a static assertion.

However, to is a tag-dispatched function, which means that to_impl may be specialized in the boost::hana namespace to customize its behavior for arbitrary data types. Also note that to is tag-dispatched using both the To and the From data types, which means that to_impl is called as to_impl<To, From>::apply(x). Also note that some concepts provide conversions to or from their models. For example, any Foldable may be converted into a Sequence. This is achieved by specializing to_impl<To, From> whenever To is a Sequence and From is a Foldable. When such conversions are provided, they are documented in the source concept, in this case Foldable.

Hana-convertibility

When an object x of data type From can be converted to a data type To using to, we say that x is Hana-convertible to the data type To. We also say that there is a Hana-conversion from From to To. This bit of terminology is useful to avoid mistaking the various kinds of conversions C++ offers.

Embeddings

As you might have seen by now, Hana uses algebraic and category- theoretical structures all around the place to help specify concepts in a rigorous way. These structures always have operations associated to them, which is why they are useful. The notion of embedding captures the idea of injecting a smaller structure into a larger one while preserving the operations of the structure. In other words, an embedding is an injective mapping that is also structure-preserving. Exactly what it means for a structure's operations to be preserved is left to explain by the documentation of each structure. For example, when we talk of a Monoid-embedding from a Monoid A to a Monoid B, we simply mean an injective transformation that preserves the identity and the associative operation, as documented in Monoid.

But what does this have to do with the to function? Quite simply, the to function is a mapping between two data types, which will sometimes be some kind of structure, and it is sometimes useful to know whether such a mapping is well-behaved, i.e. lossless and structure preserving. The criterion for this conversion to be well- behaved is exactly that of being an embedding. To specify that a conversion is an embedding, simply use the embedding type as a base class of the corresponding to_impl specialization. Obviously, you should make sure the conversion is really an embedding, unless you want to shoot yourself in the foot.

Template Parameters
ToThe data type to which x should be converted.
Parameters
xThe object to convert to the given data type.

Example

// Copyright Louis Dionne 2013-2017
// 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 <typename X, typename Y, typename Z>
struct Triple {
X first;
Y second;
Z third;
};
BOOST_HANA_CONSTEXPR_LAMBDA auto triple = [](auto x, auto y, auto z) {
return Triple<decltype(x), decltype(y), decltype(z)>{x, y, z};
};
namespace boost { namespace hana {
template <typename X, typename Y, typename Z>
struct to_impl<tuple_tag, Triple<X, Y, Z>> {
static constexpr auto apply(Triple<X, Y, Z> xs) {
return make_tuple(xs.first, xs.second, xs.third);
}
};
}}
int main() {
hana::to<hana::tuple_tag>(triple(1, '2', 3.3)) == hana::make_tuple(1, '2', 3.3)
);
}