Boost.Hana  1.5.0
Your standard library for metaprogramming
Metafunction

Description

A Metafunction is a function that takes hana::types as inputs and returns a hana::type as output.

A Metafunction is an object satisfying the FunctionObject concept, but with additional requirements. First, it must be possible to apply a Metafunction to arguments whose tag is type_tag, and the result of such an application must be an object whose tag is also type_tag. Note that hana::type and hana::basic_type are the only such types.

Secondly, a Metafunction must provide a nested ::apply template which allows performing the same type-level computation as is done by the call operator. In Boost.MPL parlance, a Metafunction F is hence a MetafunctionClass in addition to being a FunctionObject. Rigorously, the following must be satisfied by any object f of type F which is a Metafunction, and for arbitrary types T...:

f(hana::type_c<T>...) == hana::type_c<F::apply<T...>::type>

Thirdly, to ease the inter-operation of values and types, Metafunctions must also allow being called with arguments that are not hana::types. In that case, the result is equivalent to calling the metafunction on the types of the arguments. Rigorously, this means that for arbitrary objects x...,

f(x...) == f(hana::type_c<decltype(x)>...)

Minimal complete definition

The Metafunction concept does not have a minimal complete definition in terms of tag-dispatched methods. Instead, the syntactic requirements documented above should be satisfied, and the Metafunction struct should be specialized explicitly in Hana's namespace.

Concrete models

hana::metafunction, hana::metafunction_class, hana::template_

Rationale: Why aren't Metafunctions Comparable?

When seeing hana::template_, a question that naturally arises is whether Metafunctions should be made Comparable. Indeed, it would seem to make sense to compare two templates F and G with template_<F> == template_<G>. However, in the case where F and/or G are alias templates, it makes sense to talk about two types of comparisons. The first one is shallow comparison, and it determines that two alias templates are equal if they are the same alias template. The second one is deep comparison, and it determines that two template aliases are equal if they alias the same type for any template argument. For example, given F and G defined as

template <typename T>
using F = void;
template <typename T>
using G = void;

shallow comparison would determine that F and G are different because they are two different template aliases, while deep comparison would determine that F and G are equal because they always expand to the same type, void. Unfortunately, deep comparison is impossible to implement because one would have to check F and G on all possible types. On the other hand, shallow comparison is not satisfactory because Metafunctions are nothing but functions on types, and the equality of two functions is normally defined with deep comparison. Hence, we adopt a conservative stance and avoid providing comparison for Metafunctions.

Variables

template<template< typename... > class F>
constexpr auto boost::hana::template_
 Lift a template to a Metafunction.Given a template class or template alias f, template_<f> is a Metafunction satisfying. More...
 
template<template< typename... > class F>
constexpr auto boost::hana::metafunction
 Lift a MPL-style metafunction to a Metafunction.Given a MPL-style metafunction, metafunction<f> is a Metafunction satisfying. More...
 
template<typename F >
constexpr auto boost::hana::metafunction_class
 Lift a MPL-style metafunction class to a Metafunction.Given a MPL-style metafunction class, metafunction_class<f> is a Metafunction satisfying. More...
 
constexpr auto boost::hana::integral
 Turn a Metafunction into a function taking types and returning a default-constructed object.Given a Metafunction f, integral returns a new Metafunction that default-constructs an object of the type returned by f. More specifically, the following holds: More...
 
template<template< typename... > class F>
constexpr auto boost::hana::trait = hana::integral(hana::metafunction<F>)
 Alias to integral(metafunction<F>), provided for convenience. More...
 

Variable Documentation

template<template< typename... > class F>
constexpr auto boost::hana::template_

#include <boost/hana/fwd/type.hpp>

Initial value:
= [](basic_type<T>...) {
return hana::type_c<F<T...>>;
}

Lift a template to a Metafunction.Given a template class or template alias f, template_<f> is a Metafunction satisfying.

template_<f>(type_c<x>...) == type_c<f<x...>>
decltype(template_<f>)::apply<x...>::type == f<x...>
Note
In a SFINAE context, the expression template_<f>(type_c<x>...) is valid whenever the expression f<x...> is valid.

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 ...> struct f;
struct x;
struct y;
BOOST_HANA_CONSTANT_CHECK(hana::template_<f>() == hana::type_c<f<>>);
BOOST_HANA_CONSTANT_CHECK(hana::template_<f>(hana::type_c<x>) == hana::type_c<f<x>>);
BOOST_HANA_CONSTANT_CHECK(hana::template_<f>(hana::type_c<x>, hana::type_c<y>) == hana::type_c<f<x, y>>);
static_assert(std::is_same<
decltype(hana::template_<f>)::apply<x, y>::type,
f<x, y>
>::value, "");
int main() { }
template<template< typename... > class F>
constexpr auto boost::hana::metafunction

#include <boost/hana/fwd/type.hpp>

Initial value:
= [](basic_type<T>...) {
return hana::type_c<typename F<T...>::type>;
}

Lift a MPL-style metafunction to a Metafunction.Given a MPL-style metafunction, metafunction<f> is a Metafunction satisfying.

metafunction<f>(type_c<x>...) == type_c<f<x...>::type>
decltype(metafunction<f>)::apply<x...>::type == f<x...>::type
Note
In a SFINAE context, the expression metafunction<f>(type_c<x>...) is valid whenever the expression f<x...>::type is valid.

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 ...> struct f { struct type; };
struct x;
struct y;
BOOST_HANA_CONSTANT_CHECK(hana::metafunction<f>() == hana::type_c<f<>::type>);
BOOST_HANA_CONSTANT_CHECK(hana::metafunction<f>(hana::type_c<x>) == hana::type_c<f<x>::type>);
BOOST_HANA_CONSTANT_CHECK(hana::metafunction<f>(hana::type_c<x>, hana::type_c<y>) == hana::type_c<f<x, y>::type>);
static_assert(std::is_same<
decltype(hana::metafunction<f>)::apply<x, y>::type,
f<x, y>::type
>::value, "");
int main() { }
template<typename F >
constexpr auto boost::hana::metafunction_class

#include <boost/hana/fwd/type.hpp>

Initial value:
= [](basic_type<T>...) {
return hana::type_c<typename F::template apply<T...>::type>;
}
constexpr auto apply
Invokes a Callable with the given arguments.
Definition: apply.hpp:40

Lift a MPL-style metafunction class to a Metafunction.Given a MPL-style metafunction class, metafunction_class<f> is a Metafunction satisfying.

metafunction_class<f>(type_c<x>...) == type_c<f::apply<x...>::type>
decltype(metafunction_class<f>)::apply<x...>::type == f::apply<x...>::type
Note
In a SFINAE context, the expression metafunction_class<f>(type_c<x>...) is valid whenever the expression f::apply<x...>::type is valid.

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 f { template <typename ...> struct apply { struct type; }; };
struct x;
struct y;
BOOST_HANA_CONSTANT_CHECK(hana::metafunction_class<f>() == hana::type_c<f::apply<>::type>);
BOOST_HANA_CONSTANT_CHECK(hana::metafunction_class<f>(hana::type_c<x>) == hana::type_c<f::apply<x>::type>);
BOOST_HANA_CONSTANT_CHECK(hana::metafunction_class<f>(hana::type_c<x>, hana::type_c<y>) == hana::type_c<f::apply<x, y>::type>);
static_assert(std::is_same<
decltype(hana::metafunction_class<f>)::apply<x, y>::type,
f::apply<x, y>::type
>::value, "");
int main() { }
constexpr auto boost::hana::integral

#include <boost/hana/fwd/type.hpp>

Initial value:
= [](auto f) {
return [](basic_type<T>...) {
return decltype(f)::apply<T...>::type{};
};
}
constexpr auto apply
Invokes a Callable with the given arguments.
Definition: apply.hpp:40

Turn a Metafunction into a function taking types and returning a default-constructed object.Given a Metafunction f, integral returns a new Metafunction that default-constructs an object of the type returned by f. More specifically, the following holds:

integral(f)(t...) == decltype(f(t...))::type{}

The principal use case for integral is to transform Metafunctions returning a type that inherits from a meaningful base like std::integral_constant into functions returning e.g. a hana::integral_constant.

Note
  • This is not a Metafunction because it does not return a type. As such, it would not make sense to make decltype(integral(f)) a MPL metafunction class like the usual Metafunctions are.
  • When using integral with metafunctions returning std::integral_constants, don't forget to include the boost/hana/ext/std/integral_constant.hpp header to ensure Hana can interoperate with the result.
  • In a SFINAE context, the expression integral(f)(t...) is valid whenever the expression decltype(f(t...))::type is valid.

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;
constexpr auto is_void = hana::integral(hana::metafunction<std::is_void>);
BOOST_HANA_CONSTANT_CHECK(is_void(hana::type_c<void>));
BOOST_HANA_CONSTANT_CHECK(hana::not_(is_void(hana::type_c<int>)));
int main() { }
template<template< typename... > class F>
constexpr auto boost::hana::trait = hana::integral(hana::metafunction<F>)

#include <boost/hana/fwd/type.hpp>

Alias to integral(metafunction<F>), 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;
BOOST_HANA_CONSTANT_CHECK(hana::trait<std::is_integral>(hana::type_c<int>));
BOOST_HANA_CONSTANT_CHECK(hana::not_(hana::trait<std::is_integral>(hana::type_c<float>)));
int main() { }