Boost C++ Libraries Home Libraries People FAQ More

Chapter 1. Boost.Mp11

Distributed under the Boost Software License, Version 1.0.

Table of Contents

Overview
Definitions
Examples
Generating Test Cases
Computing Return Types
Reference
Integral Constants, <boost/mp11/integral.hpp>
mp_bool<B>
mp_true
mp_false
mp_to_bool<T>
mp_not<T>
mp_int<I>
mp_size_t<N>
List Operations, <boost/mp11/list.hpp>
mp_list<T...>
mp_size<L>
mp_empty<L>
mp_front<L>
mp_pop_front<L>
mp_first<L>
mp_rest<L>
mp_second<L>
mp_third<L>
mp_push_front<L, T...>
mp_push_back<L, T...>
mp_rename<L, Y>
mp_apply<F, L>
mp_append<L...>
mp_replace_front<L, T>
mp_replace_first<L, T>
mp_replace_second<L, T>
mp_replace_third<L, T>
Utility Components, <boost/mp11/utility.hpp>
mp_identity<T>
mp_identity_t<T>
mp_inherit<T...>
mp_if_c<B, T, E>
mp_if<C, T, E>
mp_eval_if_c<B, T, F, U...>
mp_eval_if<C, T, F, U...>
mp_valid<F, T...>
mp_defer<F, T...>
mp_quote<F, T...>
mp_invoke<Q, T...>
Algorithms, <boost/mp11/algorithm.hpp>
mp_assign<L1, L2>
mp_clear<L>
mp_transform<F, L...>
mp_transform_q<Q, L...>
mp_transform_if<P, F, L...>
mp_fill<L, V>
mp_count<L, V>
mp_count_if<L, P>
mp_contains<L, V>
mp_repeat_c<L, N>
mp_repeat<L, N>
mp_product<F, L...>
mp_drop_c<L, N>
mp_drop<L, N>
mp_iota_c<N>
mp_iota<N>
mp_at_c<L, I>
mp_at<L, I>
mp_take_c<L, N>
mp_take<L, N>
mp_replace<L, V, W>
mp_replace_if<L, P, W>
mp_replace_at_c<L, I, W>
mp_replace_at<L, I, W>
mp_copy_if<L, P>
mp_remove<L, V>
mp_remove_if<L, P>
mp_partition<L, P>
mp_sort<L, P>
mp_find<L, V>
mp_find_if<L, P>
mp_reverse<L>
mp_fold<L, V, F>
mp_reverse_fold<L, V, F>
mp_unique<L>
mp_all_of<L, P>
mp_none_of<L, P>
mp_any_of<L, P>
Set Operations, <boost/mp11/set.hpp>
mp_set_contains<S, V>
mp_set_push_back<S, T...>
mp_set_push_front<S, T...>
Map Operations, <boost/mp11/map.hpp>
mp_map_find<M, K>
mp_map_contains<M, K>
mp_map_insert<M, T>
mp_map_replace<M, T>
mp_map_update<M, T, F>
mp_map_erase<M, K>
Helper Metafunctions, <boost/mp11/function.hpp>
mp_and<T...>
mp_all<T...>
mp_or<T...>
mp_any<T...>
Bind, <boost/mp11/bind.hpp>
mp_arg<I>
_1, ..., _9
mp_bind<F, T...>
mp_bind_q<Q, T...>
mp_bind_front<F, T...>
mp_bind_front_q<Q, T...>
mp_bind_back<F, T...>
mp_bind_back_q<Q, T...>
Integer Sequences, <boost/integer_sequence.hpp>
integer_sequence<T, I...>
make_integer_sequence<T, N>
index_sequence<I...>
make_index_sequence<N>
index_sequence_for<T...>
A "for each" algorithm for tuple-like types, <boost/tuple_for_each.hpp>
tuple_for_each

Mp11 is a C++11 metaprogramming library based on template aliases and variadic templates. It implements the approach outlined in the article Simple C++11 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>>.

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

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

template<class T> using promote = std::common_type_t<T, int>;
template<class T, class U> using result = std::common_type_t<promote<T>, promote<U>>;

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/tuple_for_each.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 = std::common_type_t<T, int>;
template<class T, class U> using result = std::common_type_t<promote<T>, promote<U>>;

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>;
    boost::tuple_for_each( mp_product<mp_list, L, L>(), [](auto&& x){ test_result(x); } );
}

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<Qret<F>::template fn, 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.

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,

using R = mp_unique<mp_product<Qret<F>::template fn, 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<Qret<F>::template fn, 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() );
}

int main()
{
    std::variant<signed char, unsigned char, signed short, unsigned short, int, unsigned> v1( 1 );

    std::cout << "(" << name<decltype(v1)>() << ")v1: ";
    std::visit( []( auto const& x ){ std::cout << "(" << name<decltype(x)>() << ")" << x << std::endl; }, v1 );

    std::variant<int, float, double> v2( 2.0f );

    std::cout << "(" << name<decltype(v2)>() << ")v2: ";
    std::visit( []( auto const& x ){ std::cout << "(" << name<decltype(x)>() << ")" << x << std::endl; }, v2 );

    auto v3 = rvisit( []( auto const& x, auto const& y ){ return x + y; }, v1, v2 );

    std::cout << "(" << name<decltype(v3)>() << ")v3: ";
    std::visit( []( auto const& x ){ std::cout << "(" << name<decltype(x)>() << ")" << x << std::endl; }, v3 );
}

The contents of the library are in namespace boost::mp11, unless specified otherwise.

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

template<bool B> using mp_bool = std::integral_constant<bool, B>;
using mp_true = mp_bool<true>;
using mp_false = mp_bool<false>;
template<class T> using mp_to_bool = mp_bool<static_cast<bool>(T::value)>;
template<class T> using mp_not = mp_bool< !T::value >;
template<int I> using mp_int = std::integral_constant<int, I>;
template<std::size_t N> using mp_size_t = std::integral_constant<std::size_t, N>;
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.

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

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.

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.

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

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

mp_first is another name for mp_front.

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

mp_rest is another name for mp_pop_front.

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.

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.

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

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

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

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_rename<F, L<T...>> is an alias for F<T...>. (mp_apply is the same as mp_rename with the arguments reversed.)

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

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

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

mp_replace_first is another name for mp_replace_front.

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

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

template<class T> struct mp_identity
{
    using type = T;
};
template<class T> using mp_identity_t = T;
template<class... T> struct mp_inherit: T... {};
template<bool C, class T, class E> using mp_if_c = /*...*/;

mp_if_c<B, T, E> is an alias for T when B is true, for E otherwise.

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

mp_if<C, T, E> is an alias for T when C::value is true, for E otherwise.

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

mp_eval_if_c<B, T, F, U...> is an alias for T when B 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.

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.

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.

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.

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

mp_quote<F, T...> transforms the template F into a type. In the common case mp_quote<F>, the nested template fn of the result is an alias for F; otherwise, fn<U...> is an alias for F<T..., U...>, allowing partial application.

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...> is an alias for F<T...>. mp_invoke<mp_quote<F, T...>, U...> is an alias for F<T..., U...>.

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.

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.

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

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

As mp_transform, but takes a quoted metafunction.

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.

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.

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.

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

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

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.

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.

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.

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.

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.

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.

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

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.

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

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

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.

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.

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.

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

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

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.

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.

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.

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.

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

Removes all V elements of L and returns the result.

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.

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

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

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

mp_find<L, V> is 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>.

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

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

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

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.

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.

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

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

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.

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.

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.

A set is a list whose elements are unique.

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.

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.

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.

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.

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.

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.

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.

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.

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

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

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

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

mp_and<T...> is an alias for the first type U in T... for which mp_to_bool<U> is mp_false. If no such type exists, the last one is returned. mp_and<> is mp_true. Similar to std::conjunction in C++17.

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

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

mp_or<T...> is an alias for the first type U in T... for which mp_to_bool<U> is mp_true. If no such type exists, the last one is returned. mp_or<> is mp_false. Similar to std::disjunction in C++17.

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.

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

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.

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

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

As mp_bind, but takes a quoted metafunction.

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

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.

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

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.

The contents of this header are defined in namespace boost.

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.

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.

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.

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.

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.

The contents of this header are defined in namespace boost.

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<std::remove_reference_t<Tp>>::value.

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

Last revised: May 10, 2017 at 20:23:11 GMT