Boost.Hana: Core

| Boost.Hana 1.0.0 Your standard library for metaprogramming |

Classes | Typedefs | Variables
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-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 <boost/hana/core/common.hpp>
#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-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 <boost/hana/core/tag_of.hpp>
#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-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 <boost/hana/core/when.hpp>
#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-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 <boost/hana/core/is_a.hpp>
#include <boost/hana/integral_constant.hpp>
#include <boost/hana/not.hpp>
#include <boost/hana/tuple.hpp>
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-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 <boost/hana/assert.hpp>
#include <boost/hana/core/make.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/tuple.hpp>
#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

  To | The data type to which `x` should be converted.

Parameters

  x | The object to convert to the given data type.

## 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 <boost/hana/assert.hpp>
#include <boost/hana/config.hpp>
#include <boost/hana/core/to.hpp>
#include <boost/hana/equal.hpp>
#include <boost/hana/tuple.hpp>
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() {
BOOST_HANA_CONSTEXPR_CHECK(
hana::to<hana::tuple_tag>(triple(1, '2', 3.3)) == hana::make_tuple(1, '2', 3.3)
);
}