diff --git a/doc/html/mp11.html b/doc/html/mp11.html deleted file mode 100644 index fab4c02..0000000 --- a/doc/html/mp11.html +++ /dev/null @@ -1,3948 +0,0 @@ - - - - - - - - -Boost.Mp11: A C++11 metaprogramming library - - - - - -
-
-

Overview

-
-
-

Mp11 is a C++11 metaprogramming library for compile-time manipulation of data structures -that contain types. It’s based on template aliases and variadic templates and implements the -approach outlined in the article -"Simple C++ metaprogramming" -and its sequel. Reading these -articles before proceeding with this documentation is highly recommended.

-
-
-

The general principles upon which Mp11 is built are that algorithms and metafunctions are -template aliases of the form F<T…​> and data structures are lists of the form L<T…​>, -with the library placing no requirements on L. mp_list<T…​> is the built-in list type, -but std::tuple<T…​>, std::pair<T1, T2> and std::variant<T…​> are also perfectly -legitimate list types, although of course std::pair<T1, T2>, due to having exactly two elements, -is not resizeable and will consequently not work with algorithms that need to add or remove -elements.

-
-
-

Another distinguishing feature of this approach is that lists (L<T…​>) have the same form as -metafunctions (F<T…​>) and can therefore be used as such. For example, applying std::add_pointer_t -to the list std::tuple<int, float> by way of mp_transform<std::add_pointer_t, std::tuple<int, float>> -gives us std::tuple<int*, float*>, but we can also apply mp_list to the same tuple:

-
-
-
-
using R = mp_transform<mp_list, std::tuple<int, float>>;
-
-
-
-

and get std::tuple<mp_list<int>, mp_list<float>>.

-
-
-
-
-

Definitions

-
-
-

A list is a — usually but not necessarily variadic — template class whose parameters are all types, -for example mp_list<char[], void>, mp_list<>, std::tuple<int, float, char>, std::pair<int, float>, std::shared_ptr<X>.

-
-
-

A metafunction is a class template or a template alias whose parameters are all types, for example std::add_pointer_t, -std::is_const, mp_second, mp_push_front, mp_list, std::tuple, std::pair, std::shared_ptr, or

-
-
-
-
template<class...> using F1 = void;
-
-template<class T> using F2 = T*;
-
-template<class... T> using F3 = std::integral_constant<std::size_t, sizeof...(T)>;
-
-
-
-

A quoted metafunction is a class with a public metafunction member called fn, for example

-
-
-
-
struct Q1 { template<class...> using fn = void; };
-
-struct Q2 { template<class T> using fn = T*; };
-
-struct Q3 { template<class... T> using fn =
-  std::integral_constant<std::size_t, sizeof...(T)>; };
-
-
-
-

An integral constant type is a class with a public member value that is an integral constant in the C++ sense. For example, -std::integral_constant<int, 7>, or

-
-
-
-
struct N { static int constexpr value = 2; };
-
-
-
-

A set is a list whose elements are unique.

-
-
-

A map is a list of lists, the inner lists having at least one element (the key.) The keys of the map must be unique. For example,

-
-
-
-
using M1 = std::tuple<std::pair<int, int*>, std::pair<float, float*>,
-    std::pair<void, void*>>;
-
-using M2 = mp_list<mp_list<int, int*>, mp_list<float>,
-    mp_list<char, char[1], char[2]>>;
-
-
-
-
-
-

Examples

-
-
-

Generating Test Cases

-
-

Let’s suppose that we have written a metafunction result<T, U>:

-
-
-
-
template<class T> using promote = typename std::common_type<T, int>::type;
-
-template<class T, class U> using result =
-    typename std::common_type<promote<T>, promote<U>>::type;
-
-
-
-

that ought to represent the result of an arithmetic operation on the integer types T and U, -for example t + u. We want to test whether result<T, U> gives correct results for various combinations -of T and U, so we write the function

-
-
-
-
template<class T1, class T2> void test_result()
-{
-    using T3 = decltype( T1() + T2() );
-    using T4 = result<T1, T2>;
-
-    std::cout << ( std::is_same<T3, T4>::value? "[PASS]": "[FAIL]" ) << std::endl;
-}
-
-
-
-

and then need to call it a substantial number of times:

-
-
-
-
int main()
-{
-    test_result<char, char>();
-    test_result<char, short>();
-    test_result<char, int>();
-    test_result<char, unsigned>();
-    // ...
-}
-
-
-
-

Writing all those type combinations by hand is unwieldy, error prone, and worst of all, boring. This is -how we can leverage Mp11 to automate the task:

-
-
-
-
#include <boost/mp11.hpp>
-#include <boost/core/demangle.hpp>
-#include <type_traits>
-#include <iostream>
-#include <typeinfo>
-
-using namespace boost::mp11;
-
-template<class T> std::string name()
-{
-    return boost::core::demangle( typeid(T).name() );
-}
-
-template<class T> using promote = typename std::common_type<T, int>::type;
-
-template<class T, class U> using result =
-    typename std::common_type<promote<T>, promote<U>>::type;
-
-template<class T1, class T2> void test_result( mp_list<T1, T2> const& )
-{
-    using T3 = decltype( T1() + T2() );
-    using T4 = result<T1, T2>;
-
-    std::cout << ( std::is_same<T3, T4>::value? "[PASS] ": "[FAIL] " )
-        << name<T1>() << " + " << name<T2>() << " -> " << name<T3>()
-        << ", result: " << name<T4>() << std::endl;
-}
-
-int main()
-{
-    using L = std::tuple<char, short, int, unsigned, long, unsigned long>;
-    tuple_for_each( mp_product<mp_list, L, L>(), [](auto&& x){ test_result(x); } );
-}
-
-
-
-

How does it work?

-
-
-

mp_product<F, L1, L2> calls F<T1, T2> where T1 varies over the elements of L1 and T2 varies over -the elements of L2, as if by executing two nested loops. It then returns a list of these results, of the same -type as L1.

-
-
-

In our case, both lists are the same std::tuple, and F is mp_list, so mp_product<mp_list, L, L> will get us -std::tuple<mp_list<char, char>, mp_list<char, short>, mp_list<char, int>, …​, mp_list<unsigned long, long>, mp_list<unsigned long, unsigned long>>.

-
-
-

We then default-construct this tuple and pass it to tuple_for_each. tuple_for_each(tp, f) calls f for every -tuple element; we use a (C++14) lambda that calls test_result.

-
-
-

In pure C++11, we can’t use a lambda with an auto&& parameter, so we’ll have to make test_result a function object with -a templated operator() and pass that to tuple_for_each directly:

-
-
-
-
struct test_result
-{
-    template<class T1, class T2> void operator()( mp_list<T1, T2> const& ) const
-    {
-        using T3 = decltype( T1() + T2() );
-        using T4 = result<T1, T2>;
-
-        std::cout << ( std::is_same<T3, T4>::value? "[PASS] ": "[FAIL] " )
-            << name<T1>() << " + " << name<T2>() << " -> " << name<T3>()
-            << ", result: " << name<T4>() << std::endl;
-    }
-};
-
-int main()
-{
-    using L = std::tuple<char, short, int, unsigned, long, unsigned long>;
-    tuple_for_each( mp_product<mp_list, L, L>(), test_result() );
-}
-
-
-
-
-

Writing common_type Specializations

-
-

The standard trait std::common_type, used to obtain a type to which all of its arguments can convert without -unnecessary loss of precision, can be user-specialized when its default implementation (based on the ternary ?: -operator) is unsuitable.

-
-
-

Let’s write a common_type specialization for two std::tuple arguments. For that, we need a metafunction that -applies std::common_type to each pair of elements and gathers the results into a tuple:

-
-
-
-
template<class... T> using common_type_t =
-    typename std::common_type<T...>::type; // standard in C++14
-
-template<class Tp1, class Tp2> using common_tuple =
-    mp_transform<common_type_t, Tp1, Tp2>;
-
-
-
-

then specialize common_type to use it:

-
-
-
-
namespace std
-{
-
-    template<class... T1, class... T2>
-    struct common_type<std::tuple<T1...>, std::tuple<T2...>>:
-        mp_defer<common_tuple, std::tuple<T1...>, std::tuple<T2...>>
-    {
-    };
-
-} // std
-
-
-
-

(There is no need to specialize std::common_type for more than two arguments - it takes care of synthesizing the appropriate semantics from -the binary case.)

-
-
-

The subtlety here is the use of mp_defer. We could have defined a nested type to common_tuple<std::tuple<T1…​>, std::tuple<T2…​>>, -and it would still have worked in all valid cases. By letting mp_defer define type, though, we make our specialization SFINAE-friendly.

-
-
-

That is, when our common_tuple causes a substitution failure instead of a hard error, mp_defer will not define a nested type, -and common_type_t, which is defined as typename common_type<…​>::type, will also cause a substitution failure.

-
-
-

As another example, consider the hypothetical type expected<T, E…​> that represents either a successful return with a value of T, -or an unsucessful return with an error code of some type in the list E…​. The common type of expected<T1, E1, E2, E3> and -expected<T2, E1, E4, E5> is expected<common_type_t<T1, T2>, E1, E2, E3, E4, E5>. That is, the possible return values are -combined into their common type, and we take the union of the set of error types.

-
-
-

Therefore,

-
-
-
-
template<class T1, class E1, class T2, class E2> using common_expected =
-    mp_rename<mp_push_front<mp_unique<mp_append<E1, E2>>, common_type_t<T1, T2>>,
-        expected>;
-
-namespace std
-{
-
-    template<class T1, class... E1, class T2, class... E2>
-    struct common_type<expected<T1, E1...>, expected<T2, E2...>>:
-        mp_defer<common_expected, T1, mp_list<E1...>, T2, mp_list<E2...>>
-    {
-    };
-
-} // std
-
-
-
-

Here we’ve taken a different tack; instead of passing the expected types to common_expected, we’re passing the T types and lists of -the E types. This makes our job easier. mp_unique<mp_append<E1, E2>> gives us the concatenation of E1 and E2 with the duplicates -removed; we then add common_type_t<T1, T2> to the front via mp_push_front; and finally, we mp_rename the resultant mp_list -to expected.

-
-
-
-

Fixing tuple_cat

-
-

The article Simple C++11 metaprogramming builds an -implementation of the standard function tuple_cat, with the end result given below:

-
-
-
-
template<class L> using F = mp_iota<mp_size<L>>;
-
-template<class R, class...Is, class... Ks, class Tp>
-R tuple_cat_( mp_list<Is...>, mp_list<Ks...>, Tp tp )
-{
-    return R{ std::get<Ks::value>(std::get<Is::value>(tp))... };
-}
-
-template<class... Tp,
-    class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>>
-    R tuple_cat( Tp &&... tp )
-{
-    std::size_t const N = sizeof...(Tp);
-
-    // inner
-
-    using list1 = mp_list<
-        mp_rename<typename std::remove_reference<Tp>::type, mp_list>...>;
-
-    using list2 = mp_iota_c<N>;
-
-    using list3 = mp_transform<mp_fill, list1, list2>;
-
-    using inner = mp_apply<mp_append, list3>;
-
-    // outer
-
-    using list4 = mp_transform<F, list1>;
-
-    using outer = mp_apply<mp_append, list4>;
-
-    //
-
-    return tuple_cat_<R>( inner(), outer(),
-        std::forward_as_tuple( std::forward<Tp>(tp)... ) );
-}
-
-
-
-

This function, however, is not entirely correct, in that it doesn’t handle some cases properly. For example, -trying to concatenate tuples containing move-only elements such as unique_ptr fails:

-
-
-
-
std::tuple<std::unique_ptr<int>> t1;
-std::tuple<std::unique_ptr<float>> t2;
-
-auto result = ::tuple_cat( std::move( t1 ), std::move( t2 ) );
-
-
-
-

Trying to concatenate const tuples fails:

-
-
-
-
std::tuple<int> const t1;
-std::tuple<float> const t2;
-
-auto result = ::tuple_cat( t1, t2 );
-
-
-
-

And finally, the standard tuple_cat is specified to work on arbitrary tuple-like types (that is, all types -that support tuple_size, tuple_element, and get), while our implementation only works with tuple and -pair. std::array, for example, fails:

-
-
-
-
std::array<int, 2> t1{ 1, 2 };
-std::array<float, 3> t2{ 3.0f, 4.0f, 5.0f };
-
-auto result = ::tuple_cat( t1, t2 );
-
-
-
-

Let’s fix these one by one. Support for move-only types is easy, if one knows where to look. The problem is -that Tp that we’re passing to the helper tuple_cat_ is (correctly) tuple<unique_ptr<int>&&, unique_ptr<float>&&>, -but std::get<0>(tp) still returns unique_ptr<int>&, because tp is an lvalue. This behavior is a bit -surprising, but is intended to prevent inadvertent double moves.

-
-
-

Long story short, we need std::move(tp) in tuple_cat_ to make tp an rvalue:

-
-
-
-
template<class R, class...Is, class... Ks, class Tp>
-R tuple_cat_( mp_list<Is...>, mp_list<Ks...>, Tp tp )
-{
-    return R{ std::get<Ks::value>(std::get<Is::value>(std::move(tp)))... };
-}
-
-
-
-

Next, const-qualified tuples. The issue here is that we’re stripping references from the input tuples, but not -const. As a result, we’re trying to manipulate types such as tuple<int> const with Mp11 algorithms, and these -types do not fit the list concept. We just need to strip qualifiers as well, by defining the useful remove_cv_ref -primitive that is inexplicably missing from the standard library:

-
-
-
-
template<class T> using remove_cv_ref = typename std::remove_cv<
-    typename std::remove_reference<T>::type>::type;
-
-
-
-

and then by using remove_cv_ref<Tp> in place of typename std::remove_reference<Tp>::type:

-
-
-
-
template<class... Tp,
-    class R = mp_append<std::tuple<>, remove_cv_ref<Tp>...>>
-    R tuple_cat( Tp &&... tp )
-{
-    std::size_t const N = sizeof...(Tp);
-
-    // inner
-
-    using list1 = mp_list<mp_rename<remove_cv_ref<Tp>, mp_list>...>;
-
-    // ...
-
-
-
-

Finally, tuple-like types. We’ve so far exploited the fact that std::pair and std::tuple are valid Mp11 lists, -but in general, arbitrary tuple-like types aren’t, so we need to convert them into such. For that, we’ll need to -define a metafunction from_tuple_like that will take an arbitrary tuple-like type and will return, in our case, -the corresponding mp_list.

-
-
-

Technically, a more principled approach would’ve been to return std::tuple, but here mp_list will prove more -convenient.

-
-
-

What we need is, given a tuple-like type Tp, to obtain mp_list<std::tuple_element<0, Tp>::type, std::tuple_element<1, Tp>::type, -…​, std::tuple_element<N-1, Tp>::type>, where N is tuple_size<Tp>::value. Here’s one way to do it:

-
-
-
-
template<class T, class I> using tuple_element =
-    typename std::tuple_element<I::value, T>::type;
-
-template<class T> using from_tuple_like =
-    mp_product<tuple_element, mp_list<T>, mp_iota<std::tuple_size<T>>>;
-
-
-
-

(mp_iota<N> is an algorithm that returns an mp_list with elements mp_size_t<0>, mp_size_t<1>, …​, mp_size_t<N-1>.)

-
-
-

Remember that mp_product<F, L1, L2> performs the equivalent of two nested loops over the elements of L1 and L2, -applying F to the two variables and gathering the result. In our case L1 consists of the single element T, so -only the second loop (over mp_iota<N>, where N is tuple_size<T>), remains, and we get a list of the same type -as L1 (an mp_list) with contents tuple_element<T, mp_size_t<0>>, tuple_element<T, mp_size_t<1>>, …​, -tuple_element<T, mp_size_t<N-1>>.

-
-
-

For completeness’s sake, here’s another, more traditional way to achieve the same result:

-
-
-
-
template<class T> using from_tuple_like =
-    mp_transform_q<mp_bind_front<tuple_element, T>, mp_iota<std::tuple_size<T>>>;
-
-
-
-

With all these fixes applied, our fully operational tuple_cat now looks like this:

-
-
-
-
template<class L> using F = mp_iota<mp_size<L>>;
-
-template<class R, class...Is, class... Ks, class Tp>
-R tuple_cat_( mp_list<Is...>, mp_list<Ks...>, Tp tp )
-{
-    return R{ std::get<Ks::value>(std::get<Is::value>(std::move(tp)))... };
-}
-
-template<class T> using remove_cv_ref = typename std::remove_cv<
-    typename std::remove_reference<T>::type>::type;
-
-template<class T, class I> using tuple_element =
-    typename std::tuple_element<I::value, T>::type;
-
-template<class T> using from_tuple_like =
-    mp_product<tuple_element, mp_list<T>, mp_iota<std::tuple_size<T>>>;
-
-template<class... Tp,
-    class R = mp_append<std::tuple<>, from_tuple_like<remove_cv_ref<Tp>>...>>
-    R tuple_cat( Tp &&... tp )
-{
-    std::size_t const N = sizeof...(Tp);
-
-    // inner
-
-    using list1 = mp_list<from_tuple_like<remove_cv_ref<Tp>>...>;
-    using list2 = mp_iota_c<N>;
-
-    using list3 = mp_transform<mp_fill, list1, list2>;
-
-    using inner = mp_apply<mp_append, list3>;
-
-    // outer
-
-    using list4 = mp_transform<F, list1>;
-
-    using outer = mp_apply<mp_append, list4>;
-
-    //
-
-    return tuple_cat_<R>( inner(), outer(),
-        std::forward_as_tuple( std::forward<Tp>(tp)... ) );
-}
-
-
-
-
-

Computing Return Types

-
-

C++17 has a standard variant type, called std::variant. It also defines a function template -std::visit that can be used to apply a function to the contained value of one or more variants. -So for instance, if the variant v1 contains 1, and the variant v2 contains 2.0f, -std::visit(f, v1, v2) will call f(1, 2.0f).

-
-
-

However, std::visit has one limitation: it cannot return a result unless all -possible applications of the function have the same return type. If, for instance, v1 and v2 -are both of type std::variant<short, int, float>,

-
-
-
-
std::visit( []( auto const& x, auto const& y ){ return x + y; }, v1, v2 );
-
-
-
-

will fail to compile because the result of x + y can be either int or float depending on -what v1 and v2 hold.

-
-
-

A type that can hold either int or float already exists, called, surprisingly enough, std::variant<int, float>. -Let’s write our own function template rvisit that is the same as visit but returns a variant:

-
-
-
-
template<class F, class... V> auto rvisit( F&& f, V&&... v )
-{
-    using R = /*...*/;
-
-    return std::visit( [&]( auto&&... x )
-        { return R( std::forward<F>(f)( std::forward<decltype(x)>(x)... ) ); },
-        std::forward<V>( v )... );
-}
-
-
-
-

What this does is basically calls std::visit to do the work, but instead of passing it f, we pass a lambda that does the same as f except -it converts the result to a common type R. R is supposed to be std::variant<…​> where the ellipsis denotes the return types of -calling f with all possible combinations of variant values.

-
-
-

We’ll first define a helper quoted metafunction Qret<F> that returns the result of the application of F to arguments of type T…​:

-
-
-
-
template<class F> struct Qret
-{
-    template<class... T> using fn =
-        decltype( std::declval<F>()( std::declval<T>()... ) );
-};
-
-
-
-

(Unfortunately, we can’t just define this metafunction inside rvisit; the language prohibits defining template aliases inside functions.)

-
-
-

With Qret in hand, a variant of the possible return types is just a matter of applying it over the possible combinations of the variant values:

-
-
-
-
using R = mp_product_q<Qret<F>, std::remove_reference_t<V>...>;
-
-
-
-

Why does this work? mp_product<F, L1<T1…​>, L2<T2…​>, …​, Ln<Tn…​>> returns L1<F<U1, U2, …​, Un>, …​>, where Ui traverse all -possible combinations of list values. Since in our case all Li are std::variant, the result will also be std::variant. (mp_product_q is -the same as mp_product, but for quoted metafunctions such as our Qret<F>.)

-
-
-

One more step remains. Suppose that, as above, we’re passing two variants of type std::variant<short, int, float> and F is -[]( auto const& x, auto const& y ){ return x + y; }. This will generate R of length 9, one per each combination, but many of those -elements will be the same, either int or float, and we need to filter out the duplicates. So, we pass the result to mp_unique:

-
-
-
-
using R = mp_unique<mp_product_q<Qret<F>, std::remove_reference_t<V>...>>;
-
-
-
-

and we’re done:

-
-
-
-
#include <boost/mp11.hpp>
-#include <boost/core/demangle.hpp>
-#include <variant>
-#include <type_traits>
-#include <typeinfo>
-#include <iostream>
-
-using namespace boost::mp11;
-
-template<class F> struct Qret
-{
-    template<class... T> using fn =
-        decltype( std::declval<F>()( std::declval<T>()... ) );
-};
-
-template<class F, class... V> auto rvisit( F&& f, V&&... v )
-{
-    using R = mp_unique<mp_product_q<Qret<F>, std::remove_reference_t<V>...>>;
-
-    return std::visit( [&]( auto&&... x )
-        { return R( std::forward<F>(f)( std::forward<decltype(x)>(x)... ) ); },
-        std::forward<V>( v )... );
-}
-
-template<class T> std::string name()
-{
-    return boost::core::demangle( typeid(T).name() );
-}
-
-template<class V> void print_variant( char const * n, V const& v )
-{
-    std::cout << "(" << name<decltype(v)>() << ")" << n << ": ";
-
-    std::visit( []( auto const& x )
-        { std::cout << "(" << name<decltype(x)>() << ")" << x << std::endl; }, v );
-}
-
-int main()
-{
-    std::variant<char, int, float> v1( 1 );
-
-    print_variant( "v1", v1 );
-
-    std::variant<short, int, double> v2( 3.14 );
-
-    print_variant( "v2", v2 );
-
-    auto v3 = rvisit( []( auto const& x, auto const& y ){ return x + y; }, v1, v2 );
-
-    print_variant( "v3", v3 );
-}
-
-
-
-
-
-
-

Reference

-
-
-

The contents of the library are in namespace boost::mp11.

-
-
-

Integral Constants, <boost/mp11/integral.hpp>

-
-

For an Mp11 integral constant type T, T::value is an integral constant in the C++ sense.

-
-
-

mp_bool<B>

-
-
-
template<bool B> using mp_bool = std::integral_constant<bool, B>;
-
-
-
-

Same as std::bool_constant in C++17.

-
-
-
-

mp_true

-
-
-
using mp_true = mp_bool<true>;
-
-
-
-

Same as std::true_type.

-
-
-
-

mp_false

-
-
-
using mp_false = mp_bool<false>;
-
-
-
-

Same as std::false_type.

-
-
-
-

mp_to_bool<T>

-
-
-
template<class T> using mp_to_bool = mp_bool<static_cast<bool>(T::value)>;
-
-
-
-
-

mp_not<T>

-
-
-
template<class T> using mp_not = mp_bool< !T::value >;
-
-
-
-
-

mp_int<I>

-
-
-
template<int I> using mp_int = std::integral_constant<int, I>;
-
-
-
-
-

mp_size_t<N>

-
-
-
template<std::size_t N> using mp_size_t = std::integral_constant<std::size_t, N>;
-
-
-
-
-
-

List Operations, <boost/mp11/list.hpp>

-
-

mp_list<T…​>

-
-
-
template<class... T> struct mp_list {};
-
-
-
-

mp_list is the standard list type of Mp11, although the library is not restricted to it and can operate on arbitrary class templates -such as std::tuple or std::variant. Even std::pair can be used if the transformation does not alter the number of the elements in -the list.

-
-
-
-

mp_size<L>

-
-
-
template<class L> using mp_size = /*...*/;
-
-
-
-

mp_size<L> returns the number of elements in the list L, as a mp_size_t. In other words, mp_size<L<T…​>> is an alias for -mp_size_t<sizeof…​(T)>.

-
-
-
Code Example 1. Using mp_size with mp_list
-
-
using L1 = mp_list<>;
-using R1 = mp_size<L1>; // mp_size_t<0>
-
-
-
-
Code Example 2. Using mp_size with std::pair
-
-
using L2 = std::pair<int, int>;
-using R2 = mp_size<L2>; // mp_size_t<2>
-
-
-
-
Code Example 3. Using mp_size with std::tuple
-
-
using L3 = std::tuple<float>;
-using R3 = mp_size<L3>; // mp_size_t<1>
-
-
-
-
-

mp_empty<L>

-
-
-
template<class L> using mp_empty = mp_bool<mp_size<L>::value == 0>;
-
-
-
-

mp_empty<L> is an alias for mp_true if the list L is empty, for mp_false otherwise.

-
-
-
Code Example 4. Using mp_empty with std::tuple
-
-
using L1 = std::tuple<float>;
-using R1 = mp_empty<L1>; // mp_false
-
-using L2 = std::tuple<>;
-using R2 = mp_empty<L2>; // mp_true
-
-
-
-
-

mp_front<L>

-
-
-
template<class L> using mp_front = /*...*/;
-
-
-
-

mp_front<L> is the first element of the list L. That is, mp_front<L<T1, T…​>> is an alias for T1.

-
-
-
Code Example 5. Using mp_front with std::pair
-
-
using L1 = std::pair<int, float>;
-using R1 = mp_front<L1>; // int
-
-
-
-
Code Example 6. Using mp_front with std::tuple
-
-
using L2 = std::tuple<float, double, long double>;
-using R2 = mp_front<L2>; // float
-
-
-
-
Code Example 7. Using mp_front with mp_list
-
-
using L3 = mp_list<char[1], char[2], char[3], char[4]>;
-using R3 = mp_front<L3>; // char[1]
-
-
-
-
-

mp_pop_front<L>

-
-
-
template<class L> using mp_pop_front = /*...*/;
-
-
-
-

mp_pop_front<L> removes the first element of the list L. That is, mp_pop_front<L<T1, T…​>> is an alias for L<T…​>.

-
-
-
Code Example 8. Using mp_pop_front with std::tuple
-
-
using L1 = std::tuple<float, double, long double>;
-using R1 = mp_pop_front<L1>; // std::tuple<double, long double>
-
-
-
-
Code Example 9. Using mp_pop_front with mp_list
-
-
using L2 = mp_list<void>;
-using R2 = mp_pop_front<L2>; // mp_list<>
-
-
-
-
-

mp_first<L>

-
-
-
template<class L> using mp_first = mp_front<L>;
-
-
-
-

mp_first is another name for mp_front.

-
-
-
-

mp_rest<L>

-
-
-
template<class L> using mp_rest = mp_pop_front<L>;
-
-
-
-

mp_rest is another name for mp_pop_front.

-
-
-
-

mp_second<L>

-
-
-
template<class L> using mp_second = /*...*/;
-
-
-
-

mp_second<L> is the second element of the list L. That is, mp_second<L<T1, T2, T…​>> is an alias for T2.

-
-
-
Code Example 10. Using mp_second with std::pair
-
-
using L1 = std::pair<int, float>;
-using R1 = mp_second<L1>; // float
-
-
-
-
Code Example 11. Using mp_second with std::tuple
-
-
using L2 = std::tuple<float, double, long double>;
-using R2 = mp_second<L2>; // double
-
-
-
-
Code Example 12. Using mp_second with mp_list
-
-
using L3 = mp_list<char[1], char[2], char[3], char[4]>;
-using R3 = mp_second<L3>; // char[2]
-
-
-
-
-

mp_third<L>

-
-
-
template<class L> using mp_third = /*...*/;
-
-
-
-

mp_third<L> is the third element of the list L. That is, mp_third<L<T1, T2, T3, T…​>> is an alias for T3.

-
-
-
Code Example 13. Using mp_third with std::tuple
-
-
using L1 = std::tuple<float, double, long double>;
-using R1 = mp_third<L1>; // long double
-
-
-
-
Code Example 14. Using mp_third with mp_list
-
-
using L2 = mp_list<char[1], char[2], char[3], char[4]>;
-using R2 = mp_third<L2>; // char[3]
-
-
-
-
-

mp_push_front<L, T…​>

-
-
-
template<class L, class... T> using mp_push_front = /*...*/;
-
-
-
-

mp_push_front<L, T…​> inserts the elements T…​ at the front of the list L. That is, mp_push_front<L<U…​>, T…​> -is an alias for L<T…​, U…​>.

-
-
-
Code Example 15. Using mp_push_front with std::tuple
-
-
using L1 = std::tuple<double, long double>;
-using R1 = mp_push_front<L1, float>; // std::tuple<float, double, long double>
-
-
-
-
Code Example 16. Using mp_push_front with mp_list
-
-
using L2 = mp_list<void>;
-using R2 = mp_push_front<L2, char[1], char[2]>; // mp_list<char[1], char[2], void>
-
-
-
-
-

mp_push_back<L, T…​>

-
-
-
template<class L, class... T> using mp_push_back = /*...*/;
-
-
-
-

mp_push_back<L, T…​> inserts the elements T…​ at the back of the list L. That is, mp_push_back<L<U…​>, T…​> -is an alias for L<U…​, T…​>.

-
-
-
Code Example 17. Using mp_push_back with std::tuple
-
-
using L1 = std::tuple<double, long double>;
-using R1 = mp_push_back<L1, float>; // std::tuple<double, long double, float>
-
-
-
-
Code Example 18. Using mp_push_back with mp_list
-
-
using L2 = mp_list<void>;
-using R2 = mp_push_back<L2, char[1], char[2]>; // mp_list<void, char[1], char[2]>
-
-
-
-
-

mp_rename<L, Y>

-
-
-
template<class L, template<class...> class Y> using mp_rename = /*...*/;
-
-
-
-

mp_rename<L, Y> changes the type of the list L to Y. That is, mp_rename<L<T…​>, Y> is an alias for Y<T…​>.

-
-
-
Code Example 19. Using mp_rename to rename std::pair to std::tuple
-
-
using L1 = std::pair<double, long double>;
-using R1 = mp_rename<L1, std::tuple>; // std::tuple<double, long double>
-
-
-
-
Code Example 20. Using mp_rename to rename std::tuple to mp_list
-
-
using L2 = std::tuple<void>;
-using R2 = mp_rename<L2, mp_list>; // mp_list<void>
-
-
-
-
-

mp_apply<F, L>

-
-
-
template<template<class...> class F, class L> using mp_apply = mp_rename<L, F>;
-
-
-
-

mp_apply<F, L> applies the metafunction F to the contents of the list L, that is, mp_apply<F, L<T…​>> is an alias for F<T…​>. -(mp_apply is the same as mp_rename with the arguments reversed.)

-
-
-
Code Example 21. Using mp_apply with std::pair
-
-
using L1 = std::pair<double, long double>;
-using R1 = mp_apply<std::is_same, L1>; // std::is_same<double, long double>
-
-
-
-
-

mp_apply_q<Q, L>

-
-
-
template<class Q, class L> using mp_apply_q = mp_apply<Q::template fn, L>;
-
-
-
-

Same as mp_apply, but takes a quoted metafunction.

-
-
-
Code Example 22. Using mp_apply_q with mp_bind_front
-
-
using L1 = std::tuple<double, long double>;
-using L2 = mp_list<int, long>;
-
-using R1 = mp_apply_q<mp_bind_front<mp_push_back, L1>, L2>;
-  // R1 is std::tuple<double, long double, int, long>
-
-
-
-
-

mp_append<L…​>

-
-
-
template<class... L> using mp_append = /*...*/;
-
-
-
-

mp_append<L…​> concatenates the lists in L…​ into a single list that has the same type as the first list. mp_append<> -is an alias for mp_list<>. mp_append<L1<T1…​>, L2<T2…​>, …​, Ln<Tn…​>> is an alias for L1<T1…​, T2…​, …​, Tn…​>.

-
-
-
Code Example 23. Using mp_append with lists of various types
-
-
using L1 = std::tuple<double, long double>;
-using L2 = mp_list<int>;
-using L3 = std::pair<short, long>;
-using L4 = mp_list<>;
-
-using R1 = mp_append<L1, L2, L3, L4>;
-  // std::tuple<double, long double, int, short, long>
-
-
-
-
-

mp_replace_front<L, T>

-
-
-
template<class L, class T> using mp_replace_front = /*...*/;
-
-
-
-

mp_replace_front<L, T> replaces the first element of the list L with T. That is, mp_replace_front<L<U1, U…​>, T> is -an alias for L<T, U…​>.

-
-
-
Code Example 24. Using mp_replace_front with std::pair
-
-
using L1 = std::pair<int, float>;
-using R1 = mp_replace_front<L1, void>; // std::pair<void, float>
-
-
-
-
Code Example 25. Using mp_replace_front with std::tuple
-
-
using L2 = std::tuple<float, double, long double>;
-using R2 = mp_replace_front<L2, void>; // std::tuple<void, double, long double>
-
-
-
-
Code Example 26. Using mp_replace_front with mp_list
-
-
using L3 = mp_list<char[1], char[2], char[3], char[4]>;
-using R3 = mp_replace_front<L3, void>; // mp_list<void, char[2], char[3], char[4]>;
-
-
-
-
-

mp_replace_first<L, T>

-
-
-
template<class L, class T> using mp_replace_first = mp_replace_front<L, T>;
-
-
-
-

mp_replace_first is another name for mp_replace_front.

-
-
-
-

mp_replace_second<L, T>

-
-
-
template<class L, class T> using mp_replace_second = /*...*/;
-
-
-
-

mp_replace_second<L, T> replaces the second element of the list L with T. That is, mp_replace_second<L<U1, U2, U…​>, T> -is an alias for L<U1, T, U…​>.

-
-
-
Code Example 27. Using mp_replace_second with std::pair
-
-
using L1 = std::pair<int, float>;
-using R1 = mp_replace_second<L1, void>; // std::pair<int, void>
-
-
-
-
Code Example 28. Using mp_replace_second with std::tuple
-
-
using L2 = std::tuple<float, double, long double>;
-using R2 = mp_replace_second<L2, void>; // std::tuple<float, void, long double>
-
-
-
-
Code Example 29. Using mp_replace_front with mp_list
-
-
using L3 = mp_list<char[1], char[2], char[3], char[4]>;
-using R3 = mp_replace_second<L3, void>; // mp_list<char[1], void, char[3], char[4]>;
-
-
-
-
-

mp_replace_third<L, T>

-
-
-
template<class L, class T> using mp_replace_third = /*...*/;
-
-
-
-

mp_replace_third<L, T> replaces the third element of the list L with T. That is, mp_replace_third<L<U1, U2, U3, U…​>, T> -is an alias for L<U1, U2, T, U…​>.

-
-
-
Code Example 30. Using mp_replace_third with std::tuple
-
-
using L1 = std::tuple<float, double, long double>;
-using R1 = mp_replace_third<L1, void>; // std::tuple<float, double, void>
-
-
-
-
Code Example 31. Using mp_replace_third with mp_list
-
-
using L2 = mp_list<char[1], char[2], char[3], char[4]>;
-using R2 = mp_replace_third<L2, void>; // mp_list<char[1], char[2], void, char[4]>;
-
-
-
-
-
-

Utility Components, <boost/mp11/utility.hpp>

-
-

mp_identity<T>

-
-
-
template<class T> struct mp_identity
-{
-    using type = T;
-};
-
-
-
-

mp_identity is a simple transformation type trait (as per the C++ standard) -that just returns the same type. It’s useful both as such, and as a type wrapper -useful for passing types as values to functions.

-
-
-
Code Example 32. Using mp_identity as a type trait
-
-
template<class T> using addp_if_not_ref =
-    typename mp_if<std::is_reference<T>, mp_identity<T>, std::add_pointer<T>>::type;
-
-
-
-
Code Example 33. Using mp_identity to protect qualifiers and references
-
-
template<class T> void print1()
-{
-    std::cout << typeid(T).name() << std::endl;
-}
-
-template<class T> void print2()
-{
-    std::cout << typeid(mp_identity<T>).name() << std::endl;
-}
-
-int main()
-{
-    print1<int const&>(); // 'int'
-    print2<int const&>(); // 'mp_identity<int const &>'
-}
-
-
-
-
-

mp_identity_t<T>

-
-
-
template<class T> using mp_identity_t = typename mp_identity<T>::type;
-
-
-
-
-

mp_inherit<T…​>

-
-
-
template<class... T> struct mp_inherit: T... {};
-
-
-
-
-

mp_if_c<C, T, E…​>

-
-
-
template<bool C, class T, class... E> using mp_if_c = /*...*/;
-
-
-
-

mp_if_c<true, T, E…​> is an alias for T. mp_if_c<false, T, E> is an alias for E. Otherwise, the result is a substitution failure.

-
-
-
Code Example 34. Using mp_if_c to select between two alternatives
-
-
using R1 = mp_if_c<true, int, void>;  // int
-
-using R2 = mp_if_c<false, int, void>; // void
-
-
-
-
Code Example 35. Using mp_if_c to fail substitution when a condition is not met
-
-
template<class I> using void_if_5 = mp_if_c<I::value == 5, void>;
-
-
-
-

This example returns void when I::value is 5, and generates a substitution failure -otherwise. It’s the same as std::enable_if_t<I::value == 5> in C++14, or -typename std::enable_if<I::value == 5>::type in C++11.

-
-
-
-

mp_if<C, T, E…​>

-
-
-
template<class C, class T, class E...> using mp_if =
-    mp_if_c<static_cast<bool>(C::value), T, E...>;
-
-
-
-

Like mp_if_c, but the first argument is a type.

-
-
-
Code Example 36. Using mp_if to select between two alternatives
-
-
using R1 = mp_if<mp_true, int, void>;  // int
-
-using R2 = mp_if<mp_false, int, void>; // void
-
-
-
-
Code Example 37. Using mp_if to fail substitution when a condition is not met
-
-
template<class T> using void_if_const = mp_if<std::is_const<T>, void>;
-
-template<class... T> using void_if_all_const =
-    mp_if<mp_all<std::is_const<T>...>, void>;
-
-template<class T> using if_non_const = mp_if<mp_not<std::is_const<T>>, T>;
-
-
-
-
-

mp_eval_if_c<C, T, F, U…​>

-
-
-
template<bool C, class T, template<class...> class F, class... U> using mp_eval_if_c =
-    /*...*/;
-
-
-
-

mp_eval_if_c<C, T, F, U…​> is an alias for T when C is true, for F<U…​> otherwise. Its purpose -is to avoid evaluating F<U…​> when the condition is true as it may not be valid in this case.

-
-
-
Code Example 38. Using mp_eval_if_c to select the first pack element, or void
-
-
template<class... T> using first_or_void =
-    mp_eval_if_c<sizeof...(T) == 0, void, mp_apply, mp_first, mp_list<T...>>;
-
-
-
-
-

mp_eval_if<C, T, F, U…​>

-
-
-
template<class C, class T, template<class...> class F, class... U> using mp_eval_if =
-    mp_eval_if_c<static_cast<bool>(C::value), T, F, U...>;
-
-
-
-

Like mp_eval_if_c, but the first argument is a type.

-
-
-
Code Example 39. Using mp_eval_if to select the first list element, or void
-
-
template<class L> using first_or_void = mp_eval_if<mp_empty<L>, void, mp_first, L>;
-
-
-
-
-

mp_eval_if_q<C, T, Q, U…​>

-
-
-
template<class C, class T, class Q, class... U> using mp_eval_if_q =
-    mp_eval_if<C, T, Q::template fn, U...>;
-
-
-
-

Like mp_eval_if, but takes a quoted metafunction.

-
-
-
-

mp_valid<F, T…​>

-
-
-
template<template<class...> class F, class... T> using mp_valid = /*...*/;
-
-
-
-

mp_valid<F, T…​> is an alias for mp_true when F<T…​> is a valid expression, for mp_false otherwise.

-
-
-
Code Example 40. Using mp_valid to write a metafunction that checks for the existence of a nested type
-
-
template<class T> using get_nested_type = typename T::type;
-
-template<class T> struct has_nested_type: mp_valid<get_nested_type, T> {};
-
-
-
-
-

mp_defer<F, T…​>

-
-
-
template<template<class...> class F, class... T> using mp_defer = /*...*/;
-
-
-
-

When mp_valid<F, T…​> is mp_true, mp_defer<F, T…​> is a struct with a nested type type which is an alias for F<T…​>. Otherwise, -mp_defer<F, T…​> is an empty struct.

-
-
-
-

mp_quote<F>

-
-
-
template<template<class...> class F> struct mp_quote
-{
-    template<class... T> using fn = F<T...>;
-};
-
-
-
-

mp_quote<F> transforms the template F into a type with a nested template fn such that fn<T…​> returns F<T…​>.

-
-
-
Code Example 41. Using mp_quote to make a list of metafunctions
-
-
using LQ = mp_list<mp_quote<std::is_const>, mp_quote<std::is_volatile>>;
-
-
-
-
-

mp_quote_trait<F>

-
-
-
template<template<class...> class F> struct mp_quote_trait
-{
-    template<class... T> using fn = typename F<T...>::type;
-};
-
-
-
-

mp_quote_trait<F> transforms the C++03-style trait F into a quoted metafunction.

-
-
-
Code Example 42. Using mp_quote_trait with std::add_pointer
-
-
using L1 = mp_list<int, void, float>;
-using R1 = mp_transform_q<mp_quote_trait<std::add_pointer>, L1>;
-  // mp_list<int*, void*, float*>
-
-
-
-
-

mp_invoke<Q, T…​>

-
-
-
template<class Q, class... T> using mp_invoke = typename Q::template fn<T...>;
-
-
-
-

mp_invoke<Q, T…​> evaluates the nested template fn of a quoted metafunction. mp_invoke<mp_quote<F>, T…​> returns F<T…​>.

-
-
-
Code Example 43. Using mp_invoke to invoke a list of metafunctions, technique 1
-
-
using LQ = mp_list<mp_quote<std::is_const>, mp_quote<std::is_volatile>>;
-
-template<class T> using is_const_and_volatile =
-    mp_all<mp_product<mp_invoke, LQ, mp_list<T>>>;
-
-
-
-
Code Example 44. Using mp_invoke to invoke a list of metafunctions, technique 2
-
-
template<class T> using is_const_and_volatile =
-    mp_all<mp_transform_q<mp_bind_back<mp_invoke, T>, LQ>>;
-
-
-
-
Code Example 45. Using mp_invoke to invoke a list of metafunctions, technique 3
-
-
template<class T> using is_const_and_volatile =
-    mp_all<mp_transform<mp_invoke, LQ, mp_fill<LQ, T>>>;
-
-
-
-
-
-

Algorithms, <boost/mp11/algorithm.hpp>

-
-

mp_assign<L1, L2>

-
-
-
template<class L1, class L2> using mp_assign = /*...*/;
-
-
-
-

mp_assign<L1<T1…​>, L2<T2…​>> is an alias for L1<T2…​>. That is, it replaces the elements of L1 with those of L2.

-
-
-
Code Example 46. Using mp_assign with mp_list and std::tuple
-
-
using L1 = std::tuple<long>;
-using L2 = mp_list<int, float>;
-
-using R1 = mp_assign<L1, L2>; // std::tuple<int, float>
-
-
-
-
Code Example 47. Using mp_assign with mp_list and std::pair
-
-
using L1 = std::pair<long, char>;
-using L2 = mp_list<int, float>;
-
-using R1 = mp_assign<L1, L2>; // std::pair<int, float>
-
-
- - ------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Illustration 1. mp_assign

L1

A1

A2

…​

An

L2

B1

B2

…​

Bn

mp_assign<L1, L2>

B1

B2

…​

Bn

-
-
-

mp_clear<L>

-
-
-
template<class L> using mp_clear = mp_assign<L, mp_list<>>;
-
-
-
-

mp_clear<L<T…​>> is an alias for L<>, that is, it removes the elements of L.

-
-
-
Code Example 48. Using mp_clear with std::tuple
-
-
using L1 = std::tuple<int, float>;
-using R1 = mp_clear<L1>; // std::tuple<>
-
-
-
-
-

mp_transform<F, L…​>

-
-
-
template<template<class...> class F, class... L> using mp_transform = /*...*/;
-
-
-
-

mp_transform<F, L1<T1…​>, L2<T2…​>, …​, Ln<Tn…​>> applies F to each successive tuple of elements and returns L1<F<T1, T2, …​, Tn>…​>.

-
-
-
Code Example 49. Using mp_transform to produce a list of pointers from a list of pointees
-
-
template<class T> using add_pointer_t =
-    typename std::add_pointer<T>::type;  // std::add_pointer_t in C++14
-
-using L1 = std::tuple<void, int, float>;
-using R1 = mp_transform<add_pointer_t, L1>; // std::tuple<void*, int*, float*>
-
-
-
-
Code Example 50. Using mp_transform to compare the contents of two lists of types
-
-
using L1 = std::tuple<void, int, float>;
-using L2 = mp_list<void, int, float>;
-
-using R1 = mp_all<mp_transform<std::is_same, L1, L2>>; // mp_true
-
-
-
-
Code Example 51. Using mp_transform to compare the contents of two lists of integral constants
-
-
template<class T1, class T2> using eq = mp_bool<T1::value == T2::value>;
-
-using L1 = std::tuple<mp_int<1>, mp_int<2>, mp_int<3>>;
-using L2 = mp_list<mp_size_t<1>, mp_size_t<2>, mp_size_t<3>>;
-
-using R1 = mp_all<mp_transform<eq, L1, L2>>; // mp_true
-
-
- - ------- - - - - - - - - - - - - - - - - - - - -
Illustration 2. mp_transform on one list

L1

A1

A2

…​

An

mp_transform<F, L1>

F<A1>

F<A2>

…​

F<An>

- - ------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Illustration 3. mp_transform on two lists

L1

A1

A2

…​

An

L2

B1

B2

…​

Bn

mp_transform<F, L1, L2>

F<A1,B1>

F<A2,B2>

…​

F<An,Bn>

-
-
-

mp_transform_q<Q, L…​>

-
-
-
template<class Q, class... L> using mp_transform_q =
-    mp_transform<Q::template fn, L...>;
-
-
-
-

As mp_transform, but takes a quoted metafunction.

-
-
-
Code Example 52. Using mp_transform_q to count the occurences of void in a list
-
-
using L1 = std::tuple<void, int, float, void, int>;
-
-using R1 = mp_apply<mp_plus,
-    mp_transform_q<mp_bind_front<std::is_same, void>, L1>>; // mp_int<2>
-
-
- - ------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Illustration 4. mp_transform_q on two lists

L1

A1

A2

…​

An

L2

B1

B2

…​

Bn

mp_transform_q<Q, L1, L2>

Q::fn<A1,B1>

Q::fn<A2,B2>

…​

Q::fn<An,Bn>

-
-
-

mp_transform_if<P, F, L…​>

-
-
-
template<template<class...> class P, template<class...> class F, class L...>
-    using mp_transform_if = /*...*/;
-
-
-
-

mp_transform_if<P, F, L1, L2, …​, Ln> replaces the elements of the list L1 for which mp_to_bool<P<T1, T2, …​, Tn>> is mp_true with -F<T1, T2, …​, Tn>, and returns the result, where Ti are the corresponding elements of Li.

-
-
-
Code Example 53. Using mp_transform_if to replace the occurences of 'void' in a list with the corresponding elements of a second list
-
-
using L1 = std::tuple<void, int, float, void, int>;
-using L2 = std::tuple<char[1], char[2], char[3], char[4], char[5]>;
-
-template<class T1, class T2> using first_is_void = std::is_same<T1, void>;
-template<class T1, class T2> using second = T2;
-
-using R1 = mp_transform_if<first_is_void, second, L1, L2>;
-  // std::tuple<char[1], int, float, char[4], int>
-
-
- - ------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Illustration 5. mp_transform_if

L1

A1

A2

…​

An

P<Ai>

mp_false

mp_true

…​

mp_false

L2

B1

B2

…​

Bn

mp_transform_if<P, F, L1, L2>

A1

F<A2,B2>

…​

An

-
-
-

mp_transform_if_q<Qp, Qf, L…​>

-
-
-
template<class Qp, class Qf, class... L> using mp_transform_if_q =
-    mp_transform_if<Qp::template fn, Qf::template fn, L...>;
-
-
-
-

As mp_transform_if, but takes quoted metafunctions.

-
-
-
Code Example 54. Using mp_transform_if_q to replace the occurences of 'void' in a list with the corresponding elements of a second list
-
-
using L1 = std::tuple<void, int, float, void, int>;
-using L2 = std::tuple<char[1], char[2], char[3], char[4], char[5]>;
-
-using R1 = mp_transform_if_q<mp_bind<std::is_same, _1, void>, _2, L1, L2>;
-  // std::tuple<char[1], int, float, char[4], int>
-
-
- - ------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Illustration 6. mp_transform_if_q

L1

A1

A2

…​

An

Qp::fn<Ai>

mp_false

mp_true

…​

mp_false

L2

B1

B2

…​

Bn

mp_transform_if_q<Qp, _2, L1, L2>

A1

B2

…​

An

-
-
-

mp_fill<L, V>

-
-
-
template<class L, class V> using mp_fill = /*...*/;
-
-
-
-

mp_fill<L<T…​>, V> returns L<V, V, …​, V>, with the result having the same size as the input.

-
-
-
Code Example 55. Using mp_fill with std::tuple
-
-
using L1 = std::tuple<void, int, float>;
-using R1 = mp_fill<L1, double>; // std::tuple<double, double, double>
-
-
-
-
Code Example 56. Using mp_fill with std::pair
-
-
using L1 = std::pair<int, float>;
-using R1 = mp_fill<L1, void>; // std::pair<void, void>
-
-
- - ------- - - - - - - - - - - - - - - - - - - - -
Illustration 7. mp_fill

L1

A1

A2

…​

An

mp_fill<L1, V>

V

V

…​

V

-
-
-

mp_count<L, V>

-
-
-
template<class L, class V> using mp_count = /*...*/;
-
-
-
-

mp_count<L, V> returns mp_size_t<N>, where N is the number of elements of L same as V.

-
-
-
-

mp_count_if<L, P>

-
-
-
template<class L, template<class...> class P> using mp_count_if = /*...*/;
-
-
-
-

mp_count_if<L, P> returns mp_size_t<N>, where N is the number of elements T of L for which mp_to_bool<P<T>> is mp_true.

-
-
-
-

mp_contains<L, V>

-
-
-
template<class L, class V> using mp_contains = mp_to_bool<mp_count<L, V>>;
-
-
-
-

mp_contains<L, V> is mp_true when L contains an element V, mp_false otherwise.

-
-
-
-

mp_repeat_c<L, N>

-
-
-
template<class L, std::size_t N> using mp_repeat_c = /*...*/;
-
-
-
-

mp_repeat_c<L, N> returns a list of the same type as L that consists of N concatenated copies of L.

-
-
-
-

mp_repeat<L, N>

-
-
-
template<class L, class N> using mp_repeat = /*...*/;
-
-
-
-

Same as mp_repeat_c but with a type argument N. The number of copies is N::value and must be nonnegative.

-
-
-
-

mp_product<F, L…​>

-
-
-
template<template<class...> class F, class... L> using mp_product = /*...*/;
-
-
-
-

mp_product<F, L1<T1…​>, L2<T2…​>, …​, Ln<Tn…​>> evaluates F<U1, U2, …​, Un> for values Ui taken from -the Cartesian product of the lists, as if the elements Ui are formed by n nested loops, each traversing Li. -It returns a list of type L1 containing the results of the application of F.

-
- - ------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Illustration 8. mp_product on two lists

L1

A1

A2

…​

An

L2

B1

B2

…​

Bm

mp_product<F, L1, L2>

F<A1,B1>

F<A1,B2>

…​

F<A1,Bm>

F<A2,B1>

F<A2,B2>

…​

F<A2,Bm>

…​

F<An,B1>

F<An,B2>

…​

F<An,Bm>

-
-
-

mp_product_q<Q, L…​>

-
-
-
template<class Q, class... L> using mp_product_q = mp_product<Q::template fn, L...>;
-
-
-
-

As mp_product, but takes a quoted metafunction.

-
-
-
-

mp_drop_c<L, N>

-
-
-
template<class L, std::size_t N> using mp_drop_c = /*...*/;
-
-
-
-

mp_drop_c<L, N> removes the first N elements of L and returns the result.

-
- - --------- - - - - - - - - - - - - - - - - - - - - - -
Illustration 9. mp_drop_c

L1

A1

…​

Am

Am+1

…​

An

mp_drop_c<L1, M>

Am+1

…​

An

-
-
-

mp_drop<L, N>

-
-
-
template<class L, class N> using mp_drop = /*...*/;
-
-
-
-

Same as mp_drop_c, but with a type argument N. N::value must be a nonnegative number.

-
-
-
-

mp_iota_c<N>

-
-
-
template<std::size_t N> using mp_iota_c = /*...*/;
-
-
-
-

mp_iota_c<N> is an alias for mp_list<mp_size_t<0>, mp_size_t<1>, …​, mp_size_t<N-1>>.

-
-
-
-

mp_iota<N>

-
-
-
template<class N> using mp_iota = /*...*/;
-
-
-
-

Same as mp_iota_c, but with a type argument N. N::value must be a nonnegative number. Returns -mp_list<std::integral_constant<T, 0>, std::integral_constant<T, 1>, …​, std::integral_constant<T, N::value-1>> -where T is the type of N::value.

-
- - ------- - - - - - - - - - -
Illustration 10. mp_iota

mp_iota<mp_int<4>>

mp_int<0>

mp_int<1>

mp_int<2>

mp_int<3>

-
-
-

mp_at_c<L, I>

-
-
-
template<class L, std::size_t I> using mp_at_c = /*...*/;
-
-
-
-

mp_at_c<L, I> returns the I-th element of L, zero-based.

-
-
-
-

mp_at<L, I>

-
-
-
template<class L, class I> using mp_at = /*...*/;
-
-
-
-

Same as mp_at_c, but with a type argument I. I::value must be a nonnegative number.

-
-
-
-

mp_take_c<L, N>

-
-
-
template<class L, std::size_t N> using mp_take_c = /*...*/;
-
-
-
-

mp_take_c<L, N> returns a list of the same type as L containing the first N elements of L.

-
- - --------- - - - - - - - - - - - - - - - - - - - - - -
Illustration 11. mp_take_c

L1

A1

…​

Am

Am+1

…​

An

mp_take_c<L1, M>

A1

…​

Am

-
-
-

mp_take<L, N>

-
-
-
template<class L, class N> using mp_take = /*...*/;
-
-
-
-

Same as mp_take_c, but with a type argument N. N::value must be a nonnegative number.

-
-
-
-

mp_insert_c<L, I, T…​>

-
-
-
template<class L, std::size_t I, class... T> using mp_insert_c =
-    mp_append<mp_take_c<L, I>, mp_push_front<mp_drop_c<L, I>, T...>>;
-
-
-
-

Inserts the elements T…​ into the list L at position I (a zero-based index).

-
- - ----------- - - - - - - - - - - - - - - - - - - - - - - - - - - -
Illustration 12. mp_insert_c with two elements

L1

A1

…​

Am

Am+1

…​

An

mp_insert_c<L1, M, B1, B2>

A1

…​

Am

B1

B2

Am+1

…​

An

-
-
-

mp_insert<L, I, T…​>

-
-
-
template<class L, class I, class... T> using mp_insert =
-    mp_append<mp_take<L, I>, mp_push_front<mp_drop<L, I>, T...>>;
-
-
-
-

Same as mp_insert_c, but with a type argument I.

-
-
-
-

mp_erase_c<L, I, J>

-
-
-
template<class L, std::size_t I, std::size_t J> using mp_erase_c =
-    mp_append<mp_take_c<L, I>, mp_drop_c<L, J>>;
-
-
-
-

Removes from the list L the elements with indices from I (inclusive) to J (exclusive).

-
- - ------------ - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Illustration 13. mp_erase_c

L1

A0

…​

Ai-1

Ai

…​

Aj-1

Aj

…​

An-1

mp_erase_c<L1, I, J>

A0

…​

Ai-1

Aj

…​

An-1

-
-
-

mp_erase<L, I, J>

-
-
-
template<class L, class I, class J> using mp_erase =
-    mp_append<mp_take<L, I>, mp_drop<L, J>>;
-
-
-
-

Same as mp_erase_c, but with a type arguments I and J.

-
-
-
-

mp_replace<L, V, W>

-
-
-
template<class L, class V, class W> using mp_replace = /*...*/;
-
-
-
-

Replaces all V elements of L with W and returns the result.

-
- - ------- - - - - - - - - - - - - - - - - - - - -
Illustration 14. mp_replace

L1

A1

V

…​

An

mp_replace<L1, V, W>

A1

W

…​

An

-
-
-

mp_replace_if<L, P, W>

-
-
-
template<class L, template<class...> class P, class W> using mp_replace_if = /*...*/;
-
-
-
-

Replaces all T elements of L for which mp_to_bool<P<T>> is mp_true with W and returns the result.

-
- - ------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Illustration 15. mp_replace_if

L1

A1

A2

…​

An

P<Ai>

mp_false

mp_true

…​

mp_false

mp_replace_if<L1, P, W>

A1

W

…​

An

-
-
-

mp_replace_at_c<L, I, W>

-
-
-
template<class L, std::size_t I, class W> using mp_replace_at_c = /*...*/;
-
-
-
-

Replaces the element of L at zero-based index I with W and returns the result.

-
-
-
-

mp_replace_at<L, I, W>

-
-
-
template<class L, class I, class W> using mp_replace_at = /*...*/;
-
-
-
-

Same as mp_replace_at_c, but with a type argument I. I::value must be a nonnegative number.

-
-
-
-

mp_copy_if<L, P>

-
-
-
template<class L, template<class...> class P> using mp_copy_if = /*...*/;
-
-
-
-

Copies the elements T of L for which mp_to_bool<P<T>> is mp_true to a new list of the same type and returns it.

-
-
-
-

mp_remove<L, V>

-
-
-
template<class L, class V> using mp_remove = /*...*/;
-
-
-
-

Removes all V elements of L and returns the result.

-
-
-
-

mp_remove_if<L, P>

-
-
-
template<class L, template<class...> class P> using mp_remove_if = /*...*/;
-
-
-
-

Removes all elements T of L for which mp_to_bool<P<T>> is mp_true and returns the result.

-
-
-
-

mp_partition<L, P>

-
-
-
template<class L, template<class...> class P> using mp_partition = /*...*/;
-
-
-
-

mp_partition<L<T…​>, P> partitions L into two lists L<U1…​> and L<U2…​> such that mp_to_bool<P<T>> is mp_true -for the elements of L<U1…​> and mp_false for the elements of L<U2…​>. Returns L<L<U1…​>, L<U2…​>>.

-
-
-
-

mp_sort<L, P>

-
-
-
template<class L, template<class...> class P> using mp_sort = /*...*/;
-
-
-
-

mp_sort<L, P> sorts the list L according to the strict weak ordering mp_to_bool<P<T, U>>.

-
-
-
Code Example 57. Using mp_sort to sort a list of std::ratio values
-
-
#include <ratio>
-
-using L1 = mp_list<std::ratio<1,2>, std::ratio<1,4>>;
-using R1 = mp_sort<L1, std::ratio_less>; // mp_list<ratio<1,4>, ratio<1,2>>
-
-
-
-
-

mp_find<L, V>

-
-
-
template<class L, class V> using mp_find = /*...*/;
-
-
-
-

mp_find<L, V> returns the index at which the type V is located in the list L. It’s an alias for mp_size_t<I>, -where I is the zero-based index of the first occurence of V in L. If L does not contain V, mp_find<L, V> -is mp_size<L>.

-
-
-
-

mp_find_if<L, P>

-
-
-
template<class L, template<class...> class P> using mp_find_if = /*...*/;
-
-
-
-

mp_find_f<L, P> is an alias for mp_size_t<I>, where I is the zero-based index of the first element T in L for which -mp_to_bool<P<T>> is mp_true. If there is no such element, mp_find_if<L, P> is mp_size<L>.

-
-
-
-

mp_reverse<L>

-
-
-
template<class L> using mp_reverse = /*...*/;
-
-
-
-

mp_reverse<L<T1, T2, …​, Tn>> is L<Tn, …​, T2, T1>.

-
- - ------- - - - - - - - - - - - - - - - - - - - -
Illustration 16. mp_reverse

L1

A1

A2

…​

An

mp_reverse<L1>

An

An-1

…​

A1

-
-
-

mp_fold<L, V, F>

-
-
-
template<class L, class V, template<class...> class F> using mp_fold = /*...*/;
-
-
-
-

mp_fold<L<T1, T2, …​, Tn>, V, F> is F< F< F< F<V, T1>, T2>, …​>, Tn>, or V, if L is empty.

-
-
-
Code Example 58. Using mp_fold to add the contents of a list of std::ratio values
-
-
#include <ratio>
-
-using L1 = mp_list<std::ratio<1,8>, std::ratio<1,4>, std::ratio<1,2>>;
-using R1 = mp_fold<L1, std::ratio<0,1>, std::ratio_add>; // std::ratio<7,8>
-
-
-
-
-

mp_reverse_fold<L, V, F>

-
-
-
template<class L, class V, template<class...> class F> using mp_reverse_fold =
-    /*...*/;
-
-
-
-

mp_reverse_fold<L<T1, T2, …​, Tn>, V, F> is F<T1, F<T2, F<…​, F<Tn, V>>>>, or V, if L is empty.

-
-
-
-

mp_unique<L>

-
-
-
template<class L> using mp_unique = /*...*/;
-
-
-
-

mp_unique<L> returns a list of the same type as L with the duplicate elements removed.

-
-
-
-

mp_all_of<L, P>

-
-
-
template<class L, template<class...> class P> using mp_all_of =
-    mp_bool< mp_count_if<L, P>::value == mp_size<L>::value >;
-
-
-
-

mp_all_of<L, P> is mp_true when P holds for all elements of L, mp_false otherwise. When L is empty, the result is mp_true.

-
-
-
-

mp_none_of<L, P>

-
-
-
template<class L, template<class...> class P> using mp_none_of =
-    mp_bool< mp_count_if<L, P>::value == 0 >;
-
-
-
-

mp_none_of<L, P> is mp_true when P holds for no element of L, mp_false otherwise. When L is empty, the result is mp_true.

-
-
-
-

mp_any_of<L, P>

-
-
-
template<class L, template<class...> class P> using mp_any_of =
-    mp_bool< mp_count_if<L, P>::value != 0 >;
-
-
-
-

mp_any_of<L, P> is mp_true when P holds for at least one element of L, mp_false otherwise. When L is empty, the result is mp_false.

-
-
-
-

mp_for_each<L>(f)

-
-
-
template<class L, class F> constexpr F mp_for_each(F&& f);
-
-
-
-

mp_for_each<L>(f) calls f with T() for each element T of the list L, in order.

-
-
-

Returns std::forward<F>(f).

-
-
-
Code Example 59. Using mp_for_each and a C++14 lambda to print a tuple
-
-
template<class... T> void print( std::tuple<T...> const & tp )
-{
-    std::size_t const N = sizeof...(T);
-
-    mp_for_each<mp_iota_c<N>>( [&]( auto I ){
-
-        // I is mp_size_t<0>, mp_size_t<1>, ..., mp_size_t<N-1>
-
-        std::cout << std::get<I>(tp) << std::endl;
-
-    });
-}
-
-
-
-
-

mp_with_index<N>(i, f)

-
-
-
template<std::size_t N, class F>
-  constexpr auto mp_with_index( std::size_t i, F && f )
-    -> decltype(std::declval<F>()(std::declval<mp_size_t<0>>()));
-
-
-
-

mp_with_index<N>(i, f) calls f with mp_size_t<i>() and returns the result. i must be less than N. -Only constexpr on C++14 and higher.

-
-
-
-
template<class N, class F>
-  constexpr auto mp_with_index( std::size_t i, F && f )
-    -> decltype(std::declval<F>()(std::declval<mp_size_t<0>>()));
-
-
-
-

Returns mp_with_index<N::value>(i, f).

-
-
-
Code Example 60. Using mp_with_index and a C++14 lambda to print the active element of a variant
-
-
template<class... T> void print( std::variant<T...> const& v )
-{
-    mp_with_index<sizeof...(T)>( v.index(), [&]( auto I ) {
-
-        // I is mp_size_t<v.index()> here
-
-        std::cout << std::get<I>( v ) << std::endl;
-
-    });
-}
-
-
-
-
-
-

Set Operations, <boost/mp11/set.hpp>

-
-

A set is a list whose elements are unique.

-
-
-

mp_is_set<S>

-
-
-
template<class S> using mp_is_set = /*...*/;
-
-
-
-

mp_is_set<S> is mp_true if S is a set, mp_false otherwise.

-
-
-
-

mp_set_contains<S, V>

-
-
-
template<class S, class V> using mp_set_contains = /*...*/;
-
-
-
-

mp_set_contains<S, V> is mp_true if the type V is an element of the set S, mp_false otherwise.

-
-
-
-

mp_set_push_back<S, T…​>

-
-
-
template<class S, class... T> using mp_set_push_back = /*...*/;
-
-
-
-

For each T1 in T…​, mp_set_push_back<S, T…​> appends T1 to the end of S if it’s not already an element of S.

-
-
-
-

mp_set_push_front<S, T…​>

-
-
-
template<class S, class... T> using mp_set_push_front = /*...*/;
-
-
-
-

mp_set_push_front<S, T…​> inserts at the front of S those elements of T…​ for which S does not already contain the same type.

-
-
-
-
-

Map Operations, <boost/mp11/map.hpp>

-
-

A map is a list of lists, the inner lists having at least one element (the key.) The keys of the map must be unique.

-
-
-

mp_is_map<M>

-
-
-
template<class M> using mp_is_map = /*...*/;
-
-
-
-

mp_is_map<M> is mp_true if M is a map, mp_false otherwise.

-
-
-
-

mp_map_find<M, K>

-
-
-
template<class M, class K> using mp_map_find = /*...*/;
-
-
-
-

mp_map_find<M, K> is an alias for the element of the map M with a key K, or for void, if there is no such element.

-
-
-
-

mp_map_contains<M, K>

-
-
-
template<class M, class K> using mp_map_contains =
-    mp_not<std::is_same<mp_map_find<M, K>, void>>;
-
-
-
-

mp_map_contains<M, K> is mp_true if the map M contains an element with a key K, mp_false otherwise.

-
-
-
-

mp_map_insert<M, T>

-
-
-
template<class M, class T> using mp_map_insert =
-    mp_if< mp_map_contains<M, mp_first<T>>, M, mp_push_back<M, T> >;
-
-
-
-

Inserts the element T into the map M, if an element with a key mp_first<T> is not already in M.

-
-
-
-

mp_map_replace<M, T>

-
-
-
template<class M, class T> using mp_map_replace = /*...*/;
-
-
-
-

If the map M does not contain an element with a key mp_first<T>, inserts it (using mp_push_back<M, T>); otherwise, -replaces the existing element with T.

-
-
-
-

mp_map_update<M, T, F>

-
-
-
template<class M, class T, template<class...> class F> using mp_map_update = /*...*/;
-
-
-
-

If the map M does not contain an element with a key mp_first<T>, inserts it (using mp_push_back<M, T>); otherwise, -replaces the existing element L<X, Y…​> with L<X, F<X, Y…​>>.

-
-
-
-

mp_map_erase<M, K>

-
-
-
template<class M, class K> using mp_map_erase = /*...*/;
-
-
-
-

If the map M contains an element with a key K, removes it.

-
-
-
-

mp_map_keys<M>

-
-
-
template<class M> using mp_map_keys = mp_transform<mp_first, M>;
-
-
-
-

mp_map_keys<M> returns a list of the keys of M. When M is a valid map, the keys are unique, so the result is a set.

-
-
-
-
-

Helper Metafunctions, <boost/mp11/function.hpp>

-
-

mp_void<T…​>

-
-
-
template<class... T> using mp_void = void;
-
-
-
-

Same as std::void_t from C++17.

-
-
-
-

mp_and<T…​>

-
-
-
template<class... T> using mp_and = /*...*/;
-
-
-
-

mp_and<T…​> applies mp_to_bool to the types in T…​, in order. If the result of an application is mp_false, mp_and -returns mp_false. If the application causes a substitution failure, returns mp_false. If all results are mp_true, -returns mp_true. mp_and<> is mp_true.

-
-
-
Code Example 61. mp_and behavior
-
-
using R1 = mp_and<mp_true, mp_true>;   // mp_true
-
-using R2 = mp_and<mp_false, void>;     // mp_false, void is not reached
-
-using R3 = mp_and<mp_false, mp_false>; // mp_false
-
-using R4 = mp_and<void, mp_true>;      // mp_false (!)
-
-
-
-
-

mp_all<T…​>

-
-
-
template<class... T> using mp_all = /*...*/;
-
-
-
-

mp_all<T…​> is mp_true if mp_to_bool<U> is mp_true for all types U in T…​, mp_false otherwise. Same as -mp_and, but does not perform short-circuit evaluation. mp_and<mp_false, void> is mp_false, but mp_all<mp_false, void> -is an error because void does not have a nested value. The upside is that mp_all is potentially faster and does not -mask substitution failures as mp_and does.

-
-
-
Code Example 62. mp_all behavior
-
-
using R1 = mp_all<mp_true, mp_true>;   // mp_true
-
-using R2 = mp_all<mp_false, void>;     // compile-time error
-
-using R3 = mp_all<mp_false, mp_false>; // mp_false
-
-using R4 = mp_all<void, mp_true>;      // compile-time error
-
-
-
-
-

mp_or<T…​>

-
-
-
template<class... T> using mp_or = /*...*/;
-
-
-
-

mp_or<T…​> applies mp_to_bool to the types in T…​, in order. If the result of an application is mp_true, mp_or -returns mp_true. If all results are mp_false, returns mp_false. mp_or<> is mp_false.

-
-
-
Code Example 63. mp_or behavior
-
-
using R1 = mp_or<mp_true, mp_false>;   // mp_true
-
-using R2 = mp_or<mp_true, void>;       // mp_true, void is not reached
-
-using R3 = mp_or<mp_false, mp_false>;  // mp_false
-
-using R4 = mp_or<void, mp_true>;       // compile-time error
-
-
-
-
-

mp_any<T…​>

-
-
-
template<class... T> using mp_any = /*...*/;
-
-
-
-

mp_any<T…​> is mp_true if mp_to_bool<U> is mp_true for any type U in T…​, mp_false otherwise. Same as -mp_or, but does not perform short-circuit evaluation.

-
-
-
Code Example 64. mp_any behavior
-
-
using R1 = mp_any<mp_true, mp_false>;  // mp_true
-
-using R2 = mp_any<mp_true, void>;      // compile-time error
-
-using R3 = mp_any<mp_false, mp_false>; // mp_false
-
-using R4 = mp_any<void, mp_true>;      // compile-time error
-
-
-
-
-

mp_same<T…​>

-
-
-
template<class... T> using mp_same = /*...*/;
-
-
-
-

mp_same<T…​> is mp_true if all the types in T…​ are the same type, mp_false otherwise. mp_same<> is mp_true.

-
-
-
-

mp_plus<T…​>

-
-
-
template<class... T> using mp_plus = /*...*/;
-
-
-
-

mp_plus<T…​> is an integral constant type with a value that is the sum of U::value for all types U in T…​. -mp_plus<> is mp_int<0>.

-
-
-
-
-

Bind, <boost/mp11/bind.hpp>

-
-

mp_arg<I>

-
-
-
template<std::size_t I> struct mp_arg;
-
-
-
-

mp_arg<I> is a quoted metafunction whose nested template fn<T…​> returns the I-th zero-based element of T…​.

-
-
-
-

_1, …​, _9

-
-
-
using _1 = mp_arg<0>;
-using _2 = mp_arg<1>;
-using _3 = mp_arg<2>;
-using _4 = mp_arg<3>;
-using _5 = mp_arg<4>;
-using _6 = mp_arg<5>;
-using _7 = mp_arg<6>;
-using _8 = mp_arg<7>;
-using _9 = mp_arg<8>;
-
-
-
-

_1 to _9 are placeholder types, the equivalent to the placeholders of boost::bind.

-
-
-
-

mp_bind<F, T…​>

-
-
-
template<template<class...> class F, class... T> struct mp_bind;
-
-
-
-

mp_bind<F, T…​> is a quoted metafunction that implements the type-based equivalent of boost::bind. Its nested -template fn<U…​> returns F<V…​>, where V…​ is T…​ with the placeholders replaced by the corresponding element -of U…​ and the mp_bind expressions replaced with their corresponding evaluations against U…​.

-
-
-

For example, mp_bind<F, int, _2, mp_bind<G, _1>>::fn<float, void> is F<int, void, G<float>>.

-
-
-
-

mp_bind_q<Q, T…​>

-
-
-
template<class Q, class... T> using mp_bind_q = mp_bind<Q::template fn, T...>;
-
-
-
-

As mp_bind, but takes a quoted metafunction.

-
-
-
-

mp_bind_front<F, T…​>

-
-
-
template<template<class...> class F, class... T> struct mp_bind_front;
-
-
-
-

mp_bind_front<F, T…​> binds the leftmost arguments of F to T…​. Its nested template fn<U…​> returns F<T…​, U…​>.

-
-
-
-

mp_bind_front_q<Q, T…​>

-
-
-
template<class Q, class... T> using mp_bind_front_q =
-    mp_bind_front<Q::template fn, T...>;
-
-
-
-

As mp_bind_front, but takes a quoted metafunction.

-
-
-
-

mp_bind_back<F, T…​>

-
-
-
template<template<class...> class F, class... T> struct mp_bind_back;
-
-
-
-

mp_bind_back<F, T…​> binds the rightmost arguments of F to T…​. Its nested template fn<U…​> returns F<U…​, T…​>.

-
-
-
-

mp_bind_back_q<Q, T…​>

-
-
-
template<class Q, class... T> using mp_bind_back_q =
-    mp_bind_back<Q::template fn, T...>;
-
-
-
-

As mp_bind_back, but takes a quoted metafunction.

-
-
-
-
-

Integer Sequences, <boost/mp11/integer_sequence.hpp>

-
-

integer_sequence<T, I…​>

-
-
-
template<class T, T... I> struct integer_sequence
-{
-};
-
-
-
-

integer_sequence<T, I…​> holds a sequence of integers of type T. Same as C++14’s std::integer_sequence.

-
-
-
-

make_integer_sequence<T, N>

-
-
-
template<class T, T N> using make_integer_sequence = /*...*/;
-
-
-
-

make_integer_sequence<T, N> is integer_sequence<T, 0, 1, …​, N-1>. Same as C++14’s std::make_integer_sequence.

-
-
-
-

index_sequence<I…​>

-
-
-
template<std::size_t... I> using index_sequence = integer_sequence<std::size_t, I...>;
-
-
-
-

index_sequence<I…​> is an alias for integer_sequence<size_t, I…​>. Same as C++14’s std::index_sequence.

-
-
-
-

make_index_sequence<N>

-
-
-
template<std::size_t N> using make_index_sequence =
-    make_integer_sequence<std::size_t, N>;
-
-
-
-

make_index_sequence<N> is index_sequence<0, 1, …​, N-1>. Same as C++14’s std::make_index_sequence.

-
-
-
-

index_sequence_for<T…​>

-
-
-
template<class... T> using index_sequence_for =
-    make_integer_sequence<std::size_t, sizeof...(T)>;
-
-
-
-

index_sequence_for<N> is make_index_sequence<sizeof…​(T)>. Same as C++14’s std::index_sequence_for.

-
-
-
-
-

Tuple Operations, <boost/mp11/tuple.hpp>

-
-

tuple_apply(f, tp)

-
-
-
template<class F, class Tp> constexpr /*...*/ tuple_apply(F&& f, Tp&& tp);
-
-
-
-

tuple_apply(f, tp) returns std::forward<F>(f)(std::get<J>(std::forward<Tp>(tp))…​) for J in 0..N-1, -where N is std::tuple_size<typename std::remove_reference<Tp>::type>::value. Same as std::apply in C++17.

-
-
-
-

construct_from_tuple<T>(tp)

-
-
-
template<class T, class Tp> T construct_from_tuple(Tp&& tp);
-
-
-
-

construct_from_tuple<T>(tp) returns T(std::get<J>(std::forward<Tp>(tp))…​) for J in 0..N-1, -where N is std::tuple_size<typename std::remove_reference<Tp>::type>::value. Same as std::make_from_tuple in C++17. -The name of the function doesn’t match the C++17 one to avoid ambiguities when both are visible or in unqualified calls.

-
-
-
-

tuple_for_each(tp, f)

-
-
-
template<class Tp, class F> constexpr F tuple_for_each(Tp&& tp, F&& f);
-
-
-
-

tuple_for_each(tp, f) applies the function object f to each element of tp by evaluating the -expression f(std::get<J>(std::forward<Tp>(tp))) for J in 0..N-1, where N is std::tuple_size<typename std::remove_reference<Tp>::type>::value.

-
-
-

Returns std::forward<F>(f).

-
-
-
-
-

Convenience Header, <boost/mp11.hpp>

-
-

The convenience header <boost/mp11.hpp> includes all of the -headers listed previously in this reference.

-
-
-
-

MPL Support, <boost/mp11/mpl.hpp>

-
-

The header <boost/mp11/mpl.hpp>, when included, defines the -necessary support infrastructure for mp_list and std::tuple -to be valid MPL sequences.

-
-
- - - - - -
-
Note
-
-mpl.hpp is not included by <boost/mp11.hpp>. -
-
-
-
-
-
- -
-
-

This documentation is

-
-
-
    -
  • -

    Copyright 2017 Peter Dimov

    -
  • -
  • -

    Copyright 2017 Bjørn Reese

    -
  • -
-
-
-

and is distributed under the Boost Software License, Version 1.0.

-
-
-
-
- - - - \ No newline at end of file