Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

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 and data structures are lists of the form L, with the library placing no requirements on L. mp_list is the built-in list type, but std::tuple, std::pair and std::variant are also perfectly legitimate list types, although of course std::pair, 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) have the same form as metafunctions (F) and can therefore be used as such. For example, applying std::add_pointer_t to the list std::tuple by way of mp_transform> gives us std::tuple, but we can also apply mp_list to the same tuple:

using R = mp_transform>;

and get std::tuple, mp_list>.

Definitions

A list is a — usually but not necessarily variadic — template class whose parameters are all types, for example mp_list, mp_list<>, std::tuple, std::pair, std::shared_ptr.

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, 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:

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 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();
    test_result();
    test_result();
    test_result();
    // ...
}

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 
#include 
#include 
#include 
#include 

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 calls F 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 will get us std::tuple, mp_list, mp_list, …​, mp_list, mp_list>.

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>, 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 that represents either a successful return with a value of T, or an unsuccessful return with an error code of some type in the list E…​. The common type of expected and expected is expected, 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> gives us the concatenation of E1 and E2 with the duplicates removed; we then add common_type_t 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&&>, but std::get<0>(tp) still returns unique_ptr&, 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
R tuple_cat_( mp_list, mp_list, Tp tp )
{
    return R{ std::get(std::get(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 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 using remove_cv_ref = typename std::remove_cv<
    typename std::remove_reference::type>::type;

and then by using remove_cv_ref in place of typename std::remove_reference::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::type, std::tuple_element<1, Tp>::type, …​, std::tuple_element::type>, where N is tuple_size::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 is an algorithm that returns an mp_list with elements mp_size_t<0>, mp_size_t<1>, …​, mp_size_t.)

Remember that mp_product 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, where N is tuple_size), remains, and we get a list of the same type as L1 (an mp_list) with contents tuple_element>, tuple_element>, …​, tuple_element>.

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

template using from_tuple_like =
    mp_transform_q, mp_iota>>;

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,

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. 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 that returns the result of the application of F to arguments of type T…​:

template struct Qret
{
    template using fn =
        decltype( std::declval()( std::declval()... ) );
};

It turns out that C++17 already contains a metafunction that returns the result of the application of a function F to arguments of type T…​: std::invoke_result_t. We can make use of it to simplify our Qret to

template struct Qret
{
    template using fn = std::invoke_result_t;
};

which in Mp11 can be expressed more concisely as

using Qret = mp_bind_front;

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...>;

Why does this work? mp_product, L2, …​, Ln> returns L1, …​>, 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.)

One more step remains. Suppose that, as above, we’re passing two variants of type std::variant 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...>>;

and we’re done:

#include 
#include 
#include 
#include 
#include 
#include 

using namespace boost::mp11;

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

template<class F, class... V> auto rvisit( F&& f, V&&... v )
{
    using Qret = mp_bind_front<std::invoke_result_t, F>;

    using R = mp_unique<mp_product_q<Qret, remove_cv_ref<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> const 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 );
}

Revision History

Changes in 1.77.0

  • Added mp_intersperse, mp_split, mp_join

Changes in 1.75.0

  • Added mp_pairwise_fold (suggested by Barry Revzin)

  • Removed mp_invoke (use mp_invoke_q)

Changes in 1.74.0

  • Improved compilation performance of mp_with_index for large N

  • Added tuple_transform (contributed by Hans Dembinski)

Changes in 1.73.0

  • Added mp_unique_if (contributed by Kris Jusiak)

  • Added mp_flatten

  • Added mp_rotate_left, mp_rotate_right (contributed by Duncan Barber)

  • Added mp_compose

  • Added mp_power_set

  • Added mp_partial_sum

  • Added mp_iterate

Changes in 1.70.0

  • Renamed mp_invoke to mp_invoke_q

  • Added mp_similar

  • Added mp_set_union, mp_set_intersection, mp_set_difference

  • Added mp_not_fn

  • Added mp_transform_first, mp_transform_second, mp_transform_third

  • Added mp_filter

  • Added mp_eval_if_not, mp_eval_or, mp_valid_q

  • Added mp_back, mp_pop_back

  • Added BOOST_MP11_VERSION

Changes in 1.69.0

  • Removed dependency on Boost.Config; Mp11 is now standalone

  • Improved code generation for mp_with_index

  • Added mp_starts_with (contributed by Glen Fernandes)

  • Added CMake support

Reference

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

Integral Constants,

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

mp_bool

template using mp_bool = std::integral_constant;

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

mp_true

using mp_true = mp_bool;

Same as std::true_type.

mp_false

using mp_false = mp_bool;

Same as std::false_type.

mp_to_bool

template using mp_to_bool = mp_bool(T::value)>;

mp_not

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

mp_int

template using mp_int = std::integral_constant;

mp_size_t

template using mp_size_t = std::integral_constant;

List Operations,

mp_list

template 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_list_c

template using mp_list_c =
    mp_list...>;

mp_list_c produces an mp_list of the std::integral_constant types corresponding to its integer template arguments.

Code Example 1. Using mp_list_c
using L1 = mp_list_c<int, 2, 3>; // mp_list, mp_int<3>>

mp_is_list

template using mp_is_list = /*...*/;

mp_is_list is mp_true if L is a list (an instantiation of a class template whose template parameters are types), mp_false otherwise.

mp_size

template using mp_size = /*...*/;

mp_size returns the number of elements in the list L, as a mp_size_t. In other words, mp_size> is an alias for mp_size_t.

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

mp_empty

template using mp_empty = mp_bool::value == 0>;

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

Code Example 5. 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_assign

template using mp_assign = /*...*/;

mp_assign, L2> is an alias for L1. That is, it replaces the elements of L1 with those of L2.

Code Example 6. 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
Code Example 7. 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

mp_clear

template using mp_clear = mp_assign>;

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

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

mp_front

template using mp_front = /*...*/;

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

Code Example 9. Using mp_front with std::pair
using L1 = std::pair<int, float>;
using R1 = mp_front<L1>; // int
Code Example 10. Using mp_front with std::tuple
using L2 = std::tuple<float, double, long double>;
using R2 = mp_front<L2>; // float
Code Example 11. 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

template using mp_pop_front = /*...*/;

mp_pop_front removes the first element of the list L. That is, mp_pop_front> is an alias for L.

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

mp_first

template using mp_first = mp_front;

mp_first is another name for mp_front.

mp_rest

template using mp_rest = mp_pop_front;

mp_rest is another name for mp_pop_front.

mp_second

template using mp_second = /*...*/;

mp_second is the second element of the list L. That is, mp_second> is an alias for T2.

Code Example 14. Using mp_second with std::pair
using L1 = std::pair<int, float>;
using R1 = mp_second<L1>; // float
Code Example 15. Using mp_second with std::tuple
using L2 = std::tuple<float, double, long double>;
using R2 = mp_second<L2>; // double
Code Example 16. 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

template using mp_third = /*...*/;

mp_third is the third element of the list L. That is, mp_third> is an alias for T3.

Code Example 17. Using mp_third with std::tuple
using L1 = std::tuple<float, double, long double>;
using R1 = mp_third<L1>; // long double
Code Example 18. 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

template using mp_push_front = /*...*/;

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

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

mp_push_back

template using mp_push_back = /*...*/;

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

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

mp_rename

template class Y> using mp_rename = /*...*/;

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

Code Example 23. 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
Code Example 24. Using mp_rename to rename std::tuple to mp_list
using L2 = std::tuple<void>;
using R2 = mp_rename<L2, mp_list>; // mp_list

mp_apply

template class F, class L> using mp_apply = mp_rename;

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

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

mp_apply_q

template using mp_apply_q = mp_apply;

Same as mp_apply, but takes a quoted metafunction.

Code Example 26. 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

mp_append

template using mp_append = /*...*/;

mp_append 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, L2, …​, Ln> is an alias for L1.

Code Example 27. 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

mp_replace_front

template using mp_replace_front = /*...*/;

mp_replace_front replaces the first element of the list L with T. That is, mp_replace_front, T> is an alias for L.

Code Example 28. Using mp_replace_front with std::pair
using L1 = std::pair<int, float>;
using R1 = mp_replace_front<L1, void>; // std::pair
Code Example 29. Using mp_replace_front with std::tuple
using L2 = std::tuple<float, double, long double>;
using R2 = mp_replace_front<L2, void>; // std::tuple
Code Example 30. 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;

mp_replace_first

template using mp_replace_first = mp_replace_front;

mp_replace_first is another name for mp_replace_front.

mp_replace_second

template using mp_replace_second = /*...*/;

mp_replace_second replaces the second element of the list L with T. That is, mp_replace_second, T> is an alias for L.

Code Example 31. Using mp_replace_second with std::pair
using L1 = std::pair<int, float>;
using R1 = mp_replace_second<L1, void>; // std::pair
Code Example 32. Using mp_replace_second with std::tuple
using L2 = std::tuple<float, double, long double>;
using R2 = mp_replace_second<L2, void>; // std::tuple
Code Example 33. 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;

mp_replace_third

template using mp_replace_third = /*...*/;

mp_replace_third replaces the third element of the list L with T. That is, mp_replace_third, T> is an alias for L.

Code Example 34. Using mp_replace_third with std::tuple
using L1 = std::tuple<float, double, long double>;
using R1 = mp_replace_third<L1, void>; // std::tuple
Code Example 35. 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;

mp_transform_front

template class F> using mp_transform_front =
    /*...*/;

mp_transform_front replaces the first element T1 of the list L with F.

mp_transform_front_q

template using mp_transform_front_q =
    mp_transform_front;

As mp_transform_front, but takes a quoted metafunction.

mp_transform_first

template class F> using mp_transform_first =
    mp_transform_front;

mp_transform_first is another name for mp_transform_front.

mp_transform_first_q

template using mp_transform_first_q =
    mp_transform_first;

As mp_transform_first, but takes a quoted metafunction.

mp_transform_second

template class F> using mp_transform_second =
    /*...*/;

mp_transform_second replaces the second element T2 of the list L with F.

mp_transform_second_q

template using mp_transform_second_q =
    mp_transform_second;

As mp_transform_second, but takes a quoted metafunction.

mp_transform_third

template class F> using mp_transform_third =
    /*...*/;

mp_transform_third replaces the third element T3 of the list L with F.

mp_transform_third_q

template using mp_transform_third_q =
    mp_transform_third;

As mp_transform_third, but takes a quoted metafunction.

Utility Components,

mp_identity

template 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 for passing types as values to functions.

Code Example 36. 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 37. 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'
}

mp_identity_t

template using mp_identity_t = typename mp_identity::type;

mp_inherit

template struct mp_inherit: T... {};

mp_if_c

template using mp_if_c = /*...*/;

mp_if_c is an alias for T. mp_if_c is an alias for E. Otherwise, the result is a substitution failure.

Code Example 38. 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 39. 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 in C++14, or typename std::enable_if::type in C++11.

mp_if

template using mp_if =
    mp_if_c(C::value), T, E...>;

Like mp_if_c, but the first argument is a type.

Code Example 40. 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 41. 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

template class F, class... U> using mp_eval_if_c =
    /*...*/;

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

Code Example 42. 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_first, mp_list<T...>>;

mp_eval_if

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

Like mp_eval_if_c, but the first argument is a type.

Code Example 43. 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

template using mp_eval_if_q =
    mp_eval_if;

Like mp_eval_if, but takes a quoted metafunction.

mp_eval_if_not

template class F, class... U>
    using mp_eval_if_not = mp_eval_if, T, F, U...>;

Same as mp_eval_if, but the condition is reversed.

mp_eval_if_not_q

template using mp_eval_if_not_q =
    mp_eval_if_not;

Same as mp_eval_if_not, but takes a quoted metafunction.

mp_valid

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

mp_valid is an alias for mp_true when F is a valid expression, for mp_false otherwise.

Code Example 44. 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_valid_q

template using mp_valid_q = mp_valid;

Like mp_valid, but takes a quoted metafunction.

mp_eval_or

template class F, class... U> using mp_eval_or =
    mp_eval_if_not, T, F, U...>;

mp_eval_or is an alias for F when this expression is valid, for T otherwise.

Code Example 45. Using mp_eval_or to select the first pack element, or void
template<class... T> using first_or_void =
    mp_eval_or<void, mp_first, mp_list<T...>>;

mp_eval_or_q

template using mp_eval_or_q =
    mp_eval_or;

Like mp_eval_or, but takes a quoted metafunction.

mp_valid_and_true

template class F, class... T> using mp_valid_and_true =
    mp_eval_or;

mp_valid_and_true is an alias for F when this expression is valid, for mp_false otherwise.

mp_valid_and_true_q

template using mp_valid_and_true_q =
    mp_valid_and_true;

Like mp_valid_and_true, but takes a quoted metafunction.

mp_cond

template using mp_cond = /*...*/;

mp_cond is an alias for T when static_cast(C::value) is true. When static_cast(C::value) is false, it’s an alias for mp_cond.

(If static_cast(C::value) is a substitution failure, the result is too a substitution failure.)

Code Example 46. Using mp_cond
template<int N> using unsigned_ = mp_cond<
    mp_bool<N ==  8>, uint8_t,
    mp_bool<N == 16>, uint16_t,
    mp_bool<N == 32>, uint32_t,
    mp_bool<N == 64>, uint64_t,
    mp_true, unsigned // default case
>;

mp_defer

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

When mp_valid is mp_true, mp_defer is a struct with a nested type type which is an alias for F. Otherwise, mp_defer is an empty struct.

mp_quote

template class F> struct mp_quote
{
    template using fn = F;
};

mp_quote transforms the template F into a quoted metafunction, a type with a nested template fn such that fn returns F.

Code Example 47. 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

template class F> struct mp_quote_trait
{
    template using fn = typename F::type;
};

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

Code Example 48. 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

mp_invoke_q

template using mp_invoke_q = typename Q::template fn;

mp_invoke_q evaluates the nested template fn of a quoted metafunction. mp_invoke_q, T…​> returns F.

Code Example 49. Using mp_invoke_q 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_apply<mp_all, mp_product<mp_invoke_q, LQ, mp_list<T>>>;
Code Example 50. Using mp_invoke_q to invoke a list of metafunctions, technique 2
template<class T> using is_const_and_volatile =
    mp_apply<mp_all, mp_transform_q<mp_bind_back<mp_invoke_q, T>, LQ>>;
Code Example 51. Using mp_invoke_q to invoke a list of metafunctions, technique 3
template<class T> using is_const_and_volatile =
    mp_apply<mp_all, mp_transform<mp_invoke_q, LQ, mp_fill<LQ, T>>>;

mp_not_fn

template class P> struct mp_not_fn
{
    template using fn = mp_not>;
};

mp_not_fn

returns a quoted metafunction Q such that Q::fn returns mp_not>.

That is, it negates the result of P.

mp_not_fn_q

template using mp_not_fn_q = mp_not_fn;

As mp_not_fn, but takes a quoted metafunction.

mp_compose

template class... F> struct mp_compose;

mp_compose is a quoted metafunction that applies F1, F2, …​, Fn to its argument, in sequence. That is, mp_compose::fn is Fn<…​F2>…​>.

mp_compose_q

template struct mp_compose_q;

As mp_compose, but takes quoted metafunctions.

Algorithms,

mp_transform

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

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

Code Example 52. 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
Code Example 53. 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_apply<mp_all, mp_transform<std::is_same, L1, L2>>; // mp_true
Code Example 54. 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_apply<mp_all, mp_transform<eq, L1, L2>>; // mp_true
Illustration 1. mp_transform on one list

L1

A1

A2

…​

An

mp_transform

F1>

F2>

…​

Fn>

Illustration 2. mp_transform on two lists

L1

A1

A2

…​

An

L2

B1

B2

…​

Bn

mp_transform

F1,B1>

F2,B2>

…​

Fn,Bn>

mp_transform_q

template using mp_transform_q =
    mp_transform;

As mp_transform, but takes a quoted metafunction.

Code Example 55. Using mp_transform_q to count the occurrences 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 3. mp_transform_q on two lists

L1

A1

A2

…​

An

L2

B1

B2

…​

Bn

mp_transform_q

Q::fn1,B1>

Q::fn2,B2>

…​

Q::fnn,Bn>

mp_transform_if

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

mp_transform_if replaces the elements of the list L1 for which mp_to_bool> is mp_true with F, and returns the result, where Ti are the corresponding elements of Li.

Code Example 56. Using mp_transform_if to replace the occurrences 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
Illustration 4. mp_transform_if

L1

A1

A2

…​

An

L2

B1

B2

…​

Bn

Pi, Bi>

mp_false

mp_true

…​

mp_false

mp_transform_if

A1

F2,B2>

…​

An

mp_transform_if_q

template using mp_transform_if_q =
    mp_transform_if;

As mp_transform_if, but takes quoted metafunctions.

Code Example 57. Using mp_transform_if_q to replace the occurrences 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
Illustration 5. mp_transform_if_q

L1

A1

A2

…​

An

L2

B1

B2

…​

Bn

Qp::fni, Bi>

mp_false

mp_true

…​

mp_false

mp_transform_if_q

A1

B2

…​

An

mp_filter

template class P, class... L> using mp_filter = /*...*/;

mp_filter removes the elements of the list L1 for which mp_to_bool> is mp_false and returns the result, where Ti are the corresponding elements of Li.

See also mp_copy_if and mp_remove_if, less general variants of mp_filter that only take a single list.

mp_filter_q

template using mp_filter_q =
    mp_filter;

As mp_filter, but takes a quoted metafunction.

Code Example 58. Using mp_filter_q to pick elements of a list based on a mask in another list
using L1 = std::tuple<void, int, float>;
using L2 = mp_list<mp_true, mp_false, mp_true>;
using R1 = mp_filter_q<_2, L1, L2>; // std::tuple

mp_fill

template using mp_fill = /*...*/;

mp_fill, V> returns L, with the result having the same size as the input.

Code Example 59. Using mp_fill with std::tuple
using L1 = std::tuple<void, int, float>;
using R1 = mp_fill<L1, double>; // std::tuple
Code Example 60. Using mp_fill with std::pair
using L1 = std::pair<int, float>;
using R1 = mp_fill<L1, void>; // std::pair
Illustration 6. mp_fill

L1

A1

A2

…​

An

mp_fill

V

V

…​

V

mp_count

template using mp_count = /*...*/;

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

mp_count_if

template class P> using mp_count_if = /*...*/;

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

mp_count_if_q

template using mp_count_if_q = mp_count_if;

As mp_count_if, but takes a quoted metafunction.

mp_contains

template using mp_contains = mp_to_bool>;

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

mp_starts_with

template using mp_starts_with = /*...*/;

mp_starts_with is mp_true when L1 starts with L2, mp_false otherwise.

mp_repeat_c

template using mp_repeat_c = /*...*/;

mp_repeat_c returns a list of the same form as L that consists of N concatenated copies of L.

Code Example 61. Using mp_repeat_c
using L1 = tuple<int>;
using R1 = mp_repeat_c<L1, 3>; // tuple

using L2 = pair<int, float>;
using R2 = mp_repeat_c<L2, 1>; // pair

using L3 = mp_list<int, float>;
using R3 = mp_repeat_c<L3, 2>; // mp_list

using L4 = mp_list<int, float, double>;
using R4 = mp_repeat_c<L4, 0>; // mp_list<>

mp_repeat

template 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

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

mp_product, L2, …​, Ln> evaluates F 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 the form L1 containing the results of the application of F. The degenerate case of zero lists, mp_product, returns mp_list>.

Illustration 7. mp_product on two lists

L1

A1

A2

…​

An

L2

B1

B2

…​

Bm

mp_product

F1,B1>

F1,B2>

…​

F1,Bm>

F2,B1>

F2,B2>

…​

F2,Bm>

…​

Fn,B1>

Fn,B2>

…​

Fn,Bm>

mp_product_q

template using mp_product_q = mp_product;

As mp_product, but takes a quoted metafunction.

mp_power_set

template using mp_power_set = /*...*/;

mp_power_set returns a list (of the same form as L) of all possible 2n subsets of L (where n is the length of L.)

mp_power_set> returns L>.

mp_power_set> returns L, L>.

mp_power_set> returns L, L, L, L>.

mp_power_set> returns the concatenation of mp_power_set> and that same list with T1 prepended to each element.

mp_drop_c

template using mp_drop_c = /*...*/;

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

Illustration 8. mp_drop_c

L1

A1

…​

Am

Am+1

…​

An

mp_drop_c

Am+1

…​

An

mp_drop

template using mp_drop = /*...*/;

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

mp_from_sequence

template using mp_from_sequence = /*...*/

mp_from_sequence transforms an integer sequence produced by make_integer_sequence into an mp_list of the corresponding std::integral_constant types. Given

template struct S;

mp_from_sequence> is an alias for mp_list…​>.

mp_iota_c

template using mp_iota_c = /*...*/;

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

mp_iota

template 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, …​, std::integral_constant> where T is the type of N::value.

Illustration 9. mp_iota

mp_iota>

mp_int<0>

mp_int<1>

mp_int<2>

mp_int<3>

mp_at_c

template using mp_at_c = /*...*/;

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

mp_at

template using mp_at = /*...*/;

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

mp_take_c

template using mp_take_c = /*...*/;

mp_take_c returns a list of the same form as L containing the first N elements of L.

Illustration 10. mp_take_c

L1

A1

…​

Am

Am+1

…​

An

mp_take_c

A1

…​

Am

mp_take

template using mp_take = /*...*/;

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

mp_back

template using mp_back = mp_at_c::value - 1>;

mp_back returns the last element of the list L.

mp_pop_back

template using mp_pop_back = mp_take_c::value - 1>;

mp_pop_back removes the last element of the list L and returns the result.

mp_insert_c

template using mp_insert_c =
    mp_append, mp_push_front, T...>>;

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

Illustration 11. mp_insert_c with two elements

L1

A1

…​

Am

Am+1

…​

An

mp_insert_c1, B2>

A1

…​

Am

B1

B2

Am+1

…​

An

mp_insert

template using mp_insert =
    mp_append, mp_push_front, T...>>;

Same as mp_insert_c, but with a type argument I.

mp_erase_c

template using mp_erase_c =
    mp_append, mp_drop_c>;

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

Illustration 12. mp_erase_c

L1

A0

…​

Ai-1

Ai

…​

Aj-1

Aj

…​

An-1

mp_erase_c

A0

…​

Ai-1

Aj

…​

An-1

mp_erase

template using mp_erase =
    mp_append, mp_drop>;

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

mp_replace

template using mp_replace = /*...*/;

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

Illustration 13. mp_replace

L1

A1

V

…​

An

mp_replace

A1

W

…​

An

mp_replace_if

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

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

Illustration 14. mp_replace_if

L1

A1

A2

…​

An

Pi>

mp_false

mp_true

…​

mp_false

mp_replace_if

A1

W

…​

An

mp_replace_if_q

template using mp_replace_if_q =
    mp_replace_if;

As mp_replace_if, but takes a quoted metafunction.

mp_replace_at_c

template using mp_replace_at_c = /*...*/;

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

mp_replace_at

template using mp_replace_at = /*...*/;

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

mp_rotate_left_c

template using mp_rotate_left_c = /*...*/;

Moves the N % M initial elements of the list L to the back, where M is the size of L. Empty lists are unchanged.

mp_rotate_left

template using mp_rotate_left = /*...*/;

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

mp_rotate_right_c

template using mp_rotate_right_c = /*...*/;

Moves the N % M trailing elements of the list L to the front, where M is the size of L. Empty lists are unchanged.

mp_rotate_right

template using mp_rotate_right = /*...*/;

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

mp_copy_if

template class P> using mp_copy_if = /*...*/;

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

mp_copy_if_q

template using mp_copy_if_q = mp_copy_if;

As mp_copy_if, but takes a quoted metafunction.

mp_remove

template using mp_remove = /*...*/;

Removes all V elements of L and returns the result.

mp_remove_if

template class P> using mp_remove_if = /*...*/;

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

mp_remove_if_q

template using mp_remove_if_q = mp_remove_if;

As mp_remove_if, but takes a quoted metafunction.

mp_flatten

template> using mp_flatten = /*...*/;

Replaces all elements T of L that are lists of the same form as L2 (that is, those for which mp_similar is mp_true) with their elements and returns the result.

Code Example 62. Using mp_flatten
using L1 = tuple<int, tuple<>, void, tuple<float, double>>;
using R1 = mp_flatten<L1>; // tuple

using L2 = mp_list<int, mp_list<float>, tuple<void>>;
using R2a = mp_flatten<L2>; // mp_list>
using R2b = mp_flatten<L2, tuple<>>; // mp_list, void>

using L3 = mp_list<mp_list<float>, mp_list<mp_list<void>>>;
using R3 = mp_flatten<L3>; // mp_list>

mp_intersperse

template using mp_intersperse = /*...*/;

Inserts the separator S between the elements of the list L.

mp_intersperse, S> is L<>. mp_intersperse, S> is L. mp_intersperse, S> is L.

mp_split

template using mp_split = /*...*/;

Splits the list L into segments at each separator S and returns a list of the segments.

mp_split, S> is L>. mp_split, S>, where S does not occur in T…​, is L>. mp_split, S> is L, L, L>.

The segments may be empty; mp_split, S> is L, L, L<>, L<>>.

mp_join

template using mp_join = /*...*/;

mp_join is the reverse operation of mp_split; it takes a list of segments L and joins them into a single list, inserting the separator S between them.

mp_join, S> yields back the original list L.

For example, mp_split, S> gives L, L>, and mp_join, L>, S> results in L.

mp_join is equivalent to (and is implemented as) mp_apply>>.

mp_partition

template class P> using mp_partition = /*...*/;

mp_partition, P> partitions L into two lists L and L such that mp_to_bool> is mp_true for the elements of L and mp_false for the elements of L. Returns L, L>.

mp_partition_q

template using mp_partition_q = mp_partition;

As mp_partition, but takes a quoted metafunction.

mp_sort

template class P> using mp_sort = /*...*/;

mp_sort sorts the list L according to the strict weak ordering mp_to_bool>.

Code Example 63. Using mp_sort to sort a list of std::ratio values
#include 

using L1 = mp_list<std::ratio<1,2>, std::ratio<1,4>>;
using R1 = mp_sort<L1, std::ratio_less>; // mp_list, ratio<1,2>>

mp_sort_q

template using mp_sort_q = mp_sort;

As mp_sort, but takes a quoted metafunction.

mp_nth_element_c

template class P> using mp_nth_element_c =
    /*...*/;

Returns the element at position I in mp_sort.

mp_nth_element

template class P> using mp_nth_element = /*...*/;

Like mp_nth_element_c, but with a type argument I. I::value must be a nonnegative number.

mp_nth_element_q

template using mp_nth_element_q =
    mp_nth_element;

Like mp_nth_element, but takes a quoted metafunction.

mp_min_element

template class P> using mp_min_element = /*...*/;

mp_min_element returns the minimal element of the list L according to the ordering mp_to_bool>.

It’s equivalent to mp_fold, mp_first, F>, where F returns mp_if, T, U>.

mp_min_element_q

template using mp_min_element_q = mp_min_element;

As mp_min_element, but takes a quoted metafunction.

mp_max_element

template class P> using mp_max_element = /*...*/;

mp_max_element returns the maximal element of the list L according to the ordering mp_to_bool>.

It’s equivalent to mp_fold, mp_first, F>, where F returns mp_if, T, U>.

mp_max_element_q

template using mp_max_element_q = mp_max_element;

As mp_max_element, but takes a quoted metafunction.

mp_find

template using mp_find = /*...*/;

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

mp_find_if

template class P> using mp_find_if = /*...*/;

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

mp_find_if_q

template using mp_find_if_q = mp_find_if;

As mp_find_if, but takes a quoted metafunction.

mp_reverse

template using mp_reverse = /*...*/;

mp_reverse> is L.

Illustration 15. mp_reverse

L1

A1

A2

…​

An

mp_reverse

An

An-1

…​

A1

mp_fold

template class F> using mp_fold = /*...*/;

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

Code Example 64. Using mp_fold to add the contents of a list of std::ratio values
#include 

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_fold_q

template using mp_fold_q =
    mp_fold;

As mp_fold, but takes a quoted metafunction.

mp_reverse_fold

template class F> using mp_reverse_fold =
    /*...*/;

mp_reverse_fold, V, F> is F>>>, or V, if L is empty.

mp_reverse_fold_q

template using mp_reverse_fold_q =
    mp_reverse_fold;

As mp_reverse_fold, but takes a quoted metafunction.

mp_partial_sum

template class F> using mp_partial_sum = /*...*/;

mp_partial_sum is similar to mp_fold, but instead of its final result, it returns a list (of the same form as L) holding the intermediate results of the fold. The last element of the result of mp_partial_sum is the same as the result of mp_fold.

For example, mp_fold, V, F> is F, X2>, X3>, but mp_partial_sum, V, F> is mp_list, F, X2>, F, X2>, X3>>.

It’s common for F to be mp_plus, in which case the result contains the partial sums of L.

Code Example 65. Using mp_partial_sum
using L1 = mp_list_c<int, 1, 2, 3, 4>;
using R1 = mp_partial_sum<L1, mp_int<0>, mp_plus>; // mp_list_c

mp_partial_sum_q

template using mp_partial_sum_q =
    mp_partial_sum;

As mp_partial_sum, but takes a quoted metafunction.

mp_pairwise_fold

template class F> using mp_pairwise_fold = /*...*/;

mp_pairwise_fold returns a list of the same form as L whose elements are the result of the application of the binary metafunction F to each pair of adjacent elements of L. That is, mp_pairwise_fold, F> is L, F>.

The result has one fewer element than the original. If L has only one element, the result is an empty list. If L is an empty list, the result is also an empty list.

Code Example 66. Using mp_pairwise_fold
template<class L> using is_increasing = mp_all_of<
    mp_pairwise_fold<L, mp_less>, mp_to_bool>;

mp_pairwise_fold_q

template using mp_pairwise_fold_q =
    mp_pairwise_fold;

As mp_pairwise_fold, but takes a quoted metafunction.

Code Example 67. Using mp_pairwise_fold_q
template<class L, template<class...> class P> using is_sorted =
    mp_none_of<mp_pairwise_fold_q<L, mp_bind<P, _2, _1>>, mp_to_bool>;

mp_iterate

template class F, template class R>
    using mp_iterate = /*...*/;

mp_iterate applies R to V successively until that’s no longer possible, yielding the sequence V, R, R>, R>>…​

It then returns an mp_list whose elements are formed by applying F to the above sequence of values. That is, it returns mp_list, F>, F>>, …​>.

mp_iterate is in a way the reverse operation of mp_reverse_fold. Given

template struct cons {};
struct nil {};

mp_reverse_fold, nil, cons> produces cons>>, which when passed as V to mp_iterate recovers the original mp_list.

Code Example 68. Using mp_iterate
struct X1 {};
struct X2 {};
struct X3 {};

using L1 = mp_list<X1, X2, X3>;
using R1 = mp_iterate<L1, mp_first, mp_rest>; // L1

template<class T, class U> struct cons {};
struct nil {};

using V2 = mp_reverse_fold<L1, nil, cons>; // cons>>
using R2 = mp_iterate<V2, mp_first, mp_second>; // L1

struct Y1 {};
struct Y2 { using value_type = double; using next_type = Y1; };
struct Y3 { using value_type = float; using next_type = Y2; };
struct Y4 { using value_type = int; using next_type = Y3; };

template<class T> using value_type = typename T::value_type;
template<class T> using next_type = typename T::next_type;

using R3 = mp_iterate<Y4, mp_identity_t, next_type>; // mp_list
using R4 = mp_iterate<Y4, value_type, next_type>; // mp_list

mp_iterate_q

template using mp_iterate_q =
    mp_iterate;

As mp_iterate, but takes quoted metafunctions.

mp_unique

template using mp_unique = /*...*/;

mp_unique returns a list of the same form as L with the duplicate elements removed.

mp_unique_if

template class P> using mp_unique_if = /*...*/;

As mp_unique, but two elements T and U are considered duplicates when mp_to_bool> is mp_true.

mp_unique_if_q

template using mp_unique_if_q =
    mp_unique_if;

As mp_unique_if, but takes a quoted metafunction.

mp_all_of

template class P> using mp_all_of =
    mp_bool< mp_count_if::value == mp_size::value >;

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

mp_all_of_q

template using mp_all_of_q = mp_all_of;

As mp_all_of, but takes a quoted metafunction.

mp_none_of

template class P> using mp_none_of =
    mp_bool< mp_count_if::value == 0 >;

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

mp_none_of_q

template using mp_none_of_q = mp_none_of;

As mp_none_of, but takes a quoted metafunction.

mp_any_of

template class P> using mp_any_of =
    mp_bool< mp_count_if::value != 0 >;

mp_any_of 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_any_of_q

template using mp_any_of_q = mp_any_of;

As mp_any_of, but takes a quoted metafunction.

mp_for_each(f)

template constexpr F mp_for_each(F&& f);

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

Returns std::forward(f).

Code Example 69. 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

        std::cout << std::get<I>(tp) << std::endl;

    });
}

In case the elements of the list L are not default-constructible, you can use mp_for_each>, which would call f with mp_identity() instead of T().

mp_with_index(i, f)

template
  constexpr auto mp_with_index( std::size_t i, F && f )
    -> decltype(std::declval()(std::declval>()));

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

template
  constexpr auto mp_with_index( std::size_t i, F && f )
    -> decltype(std::declval()(std::declval>()));

Returns mp_with_index(i, f).

Code Example 70. 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{} here

        std::cout << std::get<I>( v ) << std::endl;

    });
}

Set Operations,

A set is a list whose elements are unique.

mp_is_set

template using mp_is_set = /*...*/;

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

mp_set_contains

template using mp_set_contains = /*...*/;

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

mp_set_push_back

template using mp_set_push_back = /*...*/;

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

mp_set_push_front

template using mp_set_push_front = /*...*/;

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

mp_set_union

template using mp_set_union = /*...*/;

mp_set_union is mp_set_push_back, where T…​ are the combined elements of the lists L…​. mp_set_union<> is mp_list<>.

mp_set_intersection

template using mp_set_intersection = /*...*/;

mp_set_intersection returns a set that contains the elements that occur in all of the sets S…​. mp_set_intersection<> is mp_list<>.

mp_set_difference

template using mp_set_difference = /*...*/;

mp_set_difference removes the elements of the list L that appear in any of the sets S…​ and returns the result.

Map Operations,

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

template using mp_is_map = /*...*/;

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

mp_map_find

template using mp_map_find = /*...*/;

mp_map_find 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

template using mp_map_contains =
    mp_not, void>>;

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

mp_map_insert

template using mp_map_insert =
    mp_if< mp_map_contains>, M, mp_push_back >;

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

mp_map_replace

template using mp_map_replace = /*...*/;

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

mp_map_update

template class F> using mp_map_update = /*...*/;

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

Code Example 71. Using mp_map_update to count the number of occurrences of types in a list
template<class T, class U> using inc2nd = mp_int<U::value + 1>;

template<class M, class T> using count_types =
    mp_map_update<M, std::pair<T, mp_int<1>>, inc2nd>;

using L1 = mp_list<float, char, float, float, float, float, char, float>;

using R1 = mp_fold<L1, std::tuple<>, count_types>;
// std::tuple>, std::pair>>

mp_map_update_q

template using mp_map_update_q =
    mp_map_update;

As mp_map_update, but takes a quoted metafunction.

mp_map_erase

template using mp_map_erase = /*...*/;

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

mp_map_keys

template using mp_map_keys = mp_transform;

mp_map_keys 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,

mp_void

template using mp_void = void;

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

mp_and

template using mp_and = /*...*/;

mp_and 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 72. 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

template using mp_all = /*...*/;

mp_all is mp_true if mp_to_bool 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 is mp_false, but mp_all 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 73. 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

template using mp_or = /*...*/;

mp_or 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 74. 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

template using mp_any = /*...*/;

mp_any is mp_true if mp_to_bool 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 75. 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

template using mp_same = /*...*/;

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

mp_similar

template using mp_similar = /*...*/;

mp_similar is mp_true if all the types in T…​ are the same type, or instantiations of the same class template whose parameters are all types, mp_false otherwise. mp_similar<> is mp_true.

Code Example 76. mp_similar
using R1 = mp_similar<void>;                        // mp_true
using R2 = mp_similar<void, void>;                  // mp_true
using R3 = mp_similar<void, void, void>;            // mp_true
using R4 = mp_similar<void, void, float>;           // mp_false

template<class T> struct X;
template<class... T> struct Y;

using R5 = mp_similar<X<int>, X<void>, X<float>>;   // mp_true
using R6 = mp_similar<Y<>, Y<void>, Y<void, void>>; // mp_true
using R7 = mp_similar<X<void>, Y<void>>;            // mp_false

mp_plus

template using mp_plus = /*...*/;

mp_plus 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>.

mp_less

template using mp_less = /*...*/;

mp_less is mp_true when the numeric value of T1::value is less than the numeric value of T2::value, mp_false otherwise.

(Note that this is not necessarily the same as T1::value < T2::value when comparing between signed and unsigned types; -1 < 1u is false, but mp_less, mp_size_t<1>> is mp_true.)

mp_min

template using mp_min = mp_min_element, mp_less>;

mp_min returns the type U in T…​ with the lowest U::value.

mp_max

template using mp_max = mp_max_element, mp_less>;

mp_max returns the type U in T…​ with the highest U::value.

Bind,

mp_arg

template struct mp_arg;

mp_arg is a quoted metafunction whose nested template fn 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

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

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

For example, mp_bind>::fn is F>.

mp_bind_q

template using mp_bind_q = mp_bind;

As mp_bind, but takes a quoted metafunction.

mp_bind_front

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

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

mp_bind_front_q

template using mp_bind_front_q =
    mp_bind_front;

As mp_bind_front, but takes a quoted metafunction.

mp_bind_back

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

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

mp_bind_back_q

template using mp_bind_back_q =
    mp_bind_back;

As mp_bind_back, but takes a quoted metafunction.

Integer Sequences,

integer_sequence

template struct integer_sequence
{
};

integer_sequence holds a sequence of integers of type T. Same as C++14’s std::integer_sequence.

make_integer_sequence

template using make_integer_sequence = /*...*/;

make_integer_sequence is integer_sequence. Same as C++14’s std::make_integer_sequence.

index_sequence

template using index_sequence = integer_sequence;

index_sequence is an alias for integer_sequence. Same as C++14’s std::index_sequence.

make_index_sequence

template using make_index_sequence =
    make_integer_sequence;

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

index_sequence_for

template using index_sequence_for =
    make_integer_sequence;

index_sequence_for is make_index_sequence. Same as C++14’s std::index_sequence_for.

Tuple Operations,

tuple_apply(f, tp)

template constexpr /*...*/ tuple_apply(F&& f, Tp&& tp);

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

construct_from_tuple(tp)

template T construct_from_tuple(Tp&& tp);

construct_from_tuple(tp) returns T(std::get(std::forward(tp))…​) for J in 0..N-1, where N is std::tuple_size::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 constexpr F tuple_for_each(Tp&& tp, F&& f);

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

Returns std::forward(f).

tuple_transform(f, tp…​)

template constexpr /*...*/ tuple_transform(F const& f, Tp&&... tp);

tuple_transform(f, tp…​) accepts a function object f followed by one or more tuples of equal length (std::tuple, std::pair and std::array are considered tuples.)

The callable f must accept as many arguments as there are tuples. The function object is called with the first elements of each tuple, with the second elements of each tuple, and so on, as if by evaluating the expression f(std::get(std::forward(tp))…​) for J in 0..N-1, where N is the length of the tuples.

The order in which the elements of the tuples are processed is unspecified.

The results are returned as a std::tuple with T…​ deduced from the return values of f (lvalue references are preserved, rvalue references are returned by value.)

Convenience Header,

The convenience header includes all of the headers listed previously in this reference.

MPL Support,

The header , 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 .

It’s also possible to only enable support for mp_list by including , and for std::tuple by including . This may be required because some libraries, such as Boost.Fusion, contain their own MPL support for std::tuple, which conflicts with Mp11’s one.

Code Example 77. Converting an existing MPL Sequence into an mp_list
using L = mpl::copy<Sequence, mpl::back_inserter<mp11::mp_list<>>>::type;

This documentation is

  • Copyright 2017-2019 Peter Dimov

  • Copyright 2017 Bjørn Reese

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

The "Simple C++11 metaprogramming" articles have been graciously converted to Asciidoc format for incorporation into this documentation by Glen Fernandes.