diff --git a/README.md b/README.md index 5c7f7fd..e36143f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -# mp11 -Simple C++11 metaprogramming library +# mp11, a simple C++11 metaprogramming library -For background, please see the article ["Simple C++11 metaprogramming"](http://pdimov.com/cpp2/simple_cxx11_metaprogramming.html) +For background, please see the article ["Simple C++11 metaprogramming"](http://pdimov.com/cpp2/simple_cxx11_metaprogramming.html). + +The library should be placed in a subdirectory `libs/mp11` in a Boost distribution. There is reference documentation in `doc/html/mp11.html`. diff --git a/doc/html/mp11.html b/doc/html/mp11.html index cfd8531..8994454 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -33,6 +33,14 @@

Table of Contents

Overview
+
Definitions
+
Examples
+
+
Generating Test + Cases
+
Computing Return + Types
+
Reference
Integral Constants, <boost/mp11/integral.hpp>
@@ -76,8 +84,8 @@ U...>
mp_valid<F, T...>
mp_defer<F, T...>
-
mp_quote<F>
-
mp_unquote<Q, T...>
+
mp_quote<F, T...>
+
mp_invoke<Q, T...>
Algorithms, <boost/mp11/algorithm.hpp>
@@ -94,8 +102,8 @@
mp_product<F, L...>
mp_drop_c<L, N>
mp_drop<L, N>
-
mp_iota_c<L, N>
-
mp_iota<L, N>
+
mp_iota_c<N>
+
mp_iota<N>
mp_at_c<L, I>
mp_at<L, I>
@@ -108,8 +116,6 @@
mp_remove_if<L, P>
mp_partition<L, P>
mp_sort<L, P>
-
mp_find_index<L, V>
-
mp_find_index_if<L, P>
mp_find<L, V>
mp_find_if<L, P>
mp_reverse<L>
@@ -136,6 +142,25 @@
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...>
+
+
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
@@ -144,17 +169,320 @@ Overview

- ... + 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 (part + 2).

+

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

+

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

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

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

+ +
+

+Definitions +

+

+ A list is a — possibly 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 + called invoke, for example +

+
struct Q1 { template<class...> using invoke = void; };
+struct Q2 { template<class T> using invoke = T*; };
+struct Q3 { template<class... T> using invoke = 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; };
+
+
+
+

+Examples +

+
+ +

+ 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 invoke = 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 invoke, 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 invoke, 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 invoke = 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 invoke, 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 );
+}
+
+

Reference

+

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

mp_bool<B> @@ -490,30 +818,32 @@

-
template<template<class...> class F> struct mp_quote
+
template<template<class...> class F, class... T> struct mp_quote
 {
-    template<class... T> using apply = F<T...>;
+    template<class... U> using invoke = F<T..., U...>;
 };
 

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

-
template<class Q, class... T> using mp_unquote = typename Q::template apply<T...>;
+
template<class Q, class... T> using mp_invoke = typename Q::template invoke<T...>;
 

- mp_unquote<Q, T...>, where Q - is mp_quote<F>, + mp_invoke<Q, T...> evaluates the nested template invoke 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...>.

@@ -527,6 +857,13 @@
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. +

@@ -534,6 +871,11 @@

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

@@ -541,6 +883,12 @@

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

@@ -548,6 +896,12 @@

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

+ mp_transform_if replaces + the elements T of L for which mp_to_bool<P<T>> is mp_true + with F<T>, + and returns the result. +

@@ -555,6 +909,11 @@

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

@@ -562,6 +921,11 @@

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

@@ -569,6 +933,12 @@

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

@@ -576,6 +946,12 @@

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

@@ -583,6 +959,10 @@

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

@@ -590,6 +970,12 @@

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

@@ -597,6 +983,15 @@

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

@@ -604,6 +999,11 @@

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

@@ -611,20 +1011,40 @@

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

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

-mp_iota_c<L, N> +mp_iota_c<N>

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

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

-mp_iota<L, N> +mp_iota<N>

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

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

@@ -632,6 +1052,10 @@

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

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

@@ -640,6 +1064,11 @@

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

@@ -647,6 +1076,11 @@

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

@@ -654,6 +1088,11 @@

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

@@ -661,6 +1100,10 @@

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

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

@@ -668,6 +1111,11 @@

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

@@ -675,6 +1123,12 @@

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

@@ -682,6 +1136,10 @@

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

+ Removes all V elements + of L and returns the result. +

@@ -689,6 +1147,12 @@

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

@@ -696,6 +1160,19 @@

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

@@ -703,34 +1180,38 @@

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

-mp_find_index<L, V> -

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

-mp_find_index_if<L, P> -

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

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

mp_find<L, V>

-
template<class L, class V> using mp_find = mp_drop<L, mp_find_index<L, V>>;
+
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>. +

mp_find_if<L, P>

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

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

@@ -738,6 +1219,9 @@

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

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

@@ -745,6 +1229,15 @@

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

@@ -752,6 +1245,11 @@

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

@@ -759,6 +1257,11 @@

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

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

@@ -766,6 +1269,13 @@

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

@@ -773,6 +1283,13 @@

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

@@ -780,6 +1297,11 @@

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

@@ -911,10 +1433,178 @@

+
+

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

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

+
+
+
+

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

+

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

+
+
+
+

+A "for each" + algorithm for tuple-like types, <boost/tuple_for_each.hpp> +

+

+ 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: March 14, 2017 at 20:19:38 GMT

Last revised: March 17, 2017 at 03:26:57 GMT


diff --git a/doc/mp11.qbk b/doc/mp11.qbk index 4b9795f..f1f55e9 100644 --- a/doc/mp11.qbk +++ b/doc/mp11.qbk @@ -23,19 +23,22 @@ [template endsimplesect[] [block '''''']] -[section Overview] - -... - -[endsect] +[include mp11/overview.qbk] +[include mp11/definitions.qbk] +[include mp11/examples.qbk] [section Reference] +The contents of the library are in namespace `boost::mp11`, unless specified otherwise. + [include mp11/integral.qbk] [include mp11/list.qbk] [include mp11/utility.qbk] [include mp11/algorithm.qbk] [include mp11/set.qbk] [include mp11/map.qbk] +[include mp11/function.qbk] +[include mp11/integer_sequence.qbk] +[include mp11/tuple_for_each.qbk] [endsect] diff --git a/doc/mp11/algorithm.qbk b/doc/mp11/algorithm.qbk index ed9edcd..ad25649 100644 --- a/doc/mp11/algorithm.qbk +++ b/doc/mp11/algorithm.qbk @@ -10,150 +10,219 @@ [section `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`. [endsect] [section `mp_clear`] template using mp_clear = mp_assign>; + +`mp_clear>` is an alias for `L<>`, that is, it removes the elements of `L`. [endsect] [section `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...>`. [endsect] [section `mp_transform_if`] template class P, template class F, class L> using mp_transform_if = /*...*/; + +`mp_transform_if` replaces the elements `T` of `L` for which `mp_to_bool>` is `mp_true` with `F`, and returns the result. [endsect] [section `mp_fill`] template using mp_fill = /*...*/; + +`mp_fill, V>` returns `L`, with the result having the same size as the input. [endsect] [section `mp_count`] template using mp_count = /*...*/; + +`mp_count` returns `mp_size_t`, where `N` is the number of elements of `L` same as `V`. [endsect] [section `mp_count_if`] template class P> using mp_count_if = /*...*/; + +`mp_count_f` returns `mp_size_t`, where `N` is the number of elements `T` of `L` for which `mp_to_bool>` is `mp_true`. [endsect] [section `mp_contains`] template using mp_contains = mp_to_bool>; + +`mp_contains` is `mp_true` when `L` contains an element `V`, `mp_false` otherwise. [endsect] [section `mp_repeat_c`] template using mp_repeat_c = /*...*/; + +`mp_repeat_c` returns a list of the same type as `L` that consists of `N` concatenated copies of `L`. [endsect] [section `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. [endsect] [section `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 type `L1` containing the results of the application of `F`. [endsect] [section `mp_drop_c`] template using mp_drop_c = /*...*/; + +`mp_drop_c` removes the first `N` elements of `L` and returns the result. [endsect] [section `mp_drop`] template using mp_drop = /*...*/; + +Same as `mp_drop_c`, but with a type argument `N`. `N::value` must be a nonnegative number. [endsect] -[section `mp_iota_c`] +[section `mp_iota_c`] template using mp_iota_c = /*...*/; + +`mp_iota_c` is an alias for `mp_list, mp_size_t<1>, ..., mp_size_t>`. [endsect] -[section `mp_iota`] +[section `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`. [endsect] [section `mp_at_c`] template using mp_at_c = /*...*/; + +`mp_at_c` returns the `I`th element of `L`, zero-based. [endsect] [section `mp_at`] template using mp_at = /*...*/; + +Same as `mp_at_c`, but with a type argument `I`. `I::value` must be a nonnegative number. [endsect] [section `mp_take_c`] template using mp_take_c = /*...*/; + +`mp_take_c` returns a list of the same type as `L` containing the first `N` elements of `L`. [endsect] [section `mp_take`] template using mp_take = /*...*/; + +Same as `mp_take_c`, but with a type argument `N`. `N::value` must be a nonnegative number. [endsect] [section `mp_replace`] template using mp_replace = /*...*/; + +Replaces all `V` elements of `L` with `W` and returns the result. [endsect] [section `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. [endsect] [section `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 type and returns it. [endsect] [section `mp_remove`] template using mp_remove = /*...*/; + +Removes all `V` elements of `L` and returns the result. [endsect] [section `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. [endsect] [section `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>`. [endsect] [section `mp_sort`] template class P> using mp_sort = /*...*/; -[endsect] -[section `mp_find_index`] - template using mp_find_index = /*...*/; -[endsect] - -[section `mp_find_index_if`] - template class P> using mp_find_index_if = /*...*/; +`mp_sort` sorts the list `L` according to the strict weak ordering `mp_to_bool>`. [endsect] [section `mp_find`] - template using mp_find = mp_drop>; + template using mp_find = /*...*/; + +`mp_find` is an alias for `mp_size_t`, where `I` is the zero-based index of the first occurence of `V` in `L`. If +`L` does not contain `V`, `mp_find` is `mp_size`. [endsect] [section `mp_find_if`] - template class P> using mp_find_if = mp_drop>; + 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` is `mp_size`. [endsect] [section `mp_reverse`] template using mp_reverse = /*...*/; + +`mp_reverse>` is `L`. [endsect] [section `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. [endsect] [section `mp_reverse_fold`] template class F> using mp_reverse_fold = /*...*/; + +`mp_reverse_fold, V, F>` is `F>>>`, or `V`, if `L` is empty. [endsect] [section `mp_unique`] template using mp_unique = /*...*/; + +`mp_unique` returns a list of the same type as `L` with the duplicate elements removed. [endsect] [section `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`. [endsect] [section `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`. [endsect] [section `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`. [endsect] [endsect] diff --git a/doc/mp11/definitions.qbk b/doc/mp11/definitions.qbk new file mode 100644 index 0000000..9a6cd8d --- /dev/null +++ b/doc/mp11/definitions.qbk @@ -0,0 +1,32 @@ +[/ + / Copyright 2017 Peter Dimov + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[section Definitions] + +A /list/ is a '''—''' possibly 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 using F1 = void; + template using F2 = T*; + template using F3 = std::integral_constant; + +A /quoted metafunction/ is a class with a public metafunction called `invoke`, for example + + struct Q1 { template using invoke = void; }; + struct Q2 { template using invoke = T*; }; + struct Q3 { template using invoke = std::integral_constant; }; + +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; }; + +[endsect] diff --git a/doc/mp11/examples.qbk b/doc/mp11/examples.qbk new file mode 100644 index 0000000..1b5a367 --- /dev/null +++ b/doc/mp11/examples.qbk @@ -0,0 +1,175 @@ +[/ + / Copyright 2017 Peter Dimov + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[section Examples] + +[section Generating Test Cases] + +Let's suppose that we have written a metafunction `result`: + + template using promote = std::common_type_t; + template using result = std::common_type_t, promote>; + +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 void test_result() + { + using T3 = decltype( T1() + T2() ); + using T4 = result; + + std::cout << ( std::is_same::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 + #include + + using namespace boost::mp11; + + template std::string name() + { + return boost::core::demangle( typeid(T).name() ); + } + + template using promote = std::common_type_t; + template using result = std::common_type_t, promote>; + + template void test_result( mp_list const& ) + { + using T3 = decltype( T1() + T2() ); + using T4 = result; + + std::cout << ( std::is_same::value? "[PASS] ": "[FAIL] " ) << name() << " + " << name() << " -> " << name() << ", result: " << name() << " " << std::endl; + } + + int main() + { + using L = std::tuple; + boost::tuple_for_each( mp_product(), [](auto&& x){ test_result(x); } ); + } + +[endsect] + +[section 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 `variant`s. +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 auto rvisit( F&& f, V&&... v ) + { + using R = /*...*/; + return std::visit( [&]( auto&&... x ){ return R( std::forward(f)( std::forward(x)... ) ); }, std::forward( 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 invoke = decltype( std::declval()( std::declval()... ) ); + }; + +(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::template invoke, std::remove_reference_t...>; + +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`. + +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, + + using R = mp_unique::template invoke, std::remove_reference_t...>>; + +and we're done: + + #include + #include + #include + #include + #include + #include + + using namespace boost::mp11; + + template struct Qret + { + template using invoke = decltype( std::declval()( std::declval()... ) ); + }; + + template auto rvisit( F&& f, V&&... v ) + { + using R = mp_unique::template invoke, std::remove_reference_t...>>; + return std::visit( [&]( auto&&... x ){ return R( std::forward(f)( std::forward(x)... ) ); }, std::forward( v )... ); + } + + template std::string name() + { + return boost::core::demangle( typeid(T).name() ); + } + + int main() + { + std::variant v1( 1 ); + + std::cout << "(" << name() << ")v1: "; + std::visit( []( auto const& x ){ std::cout << "(" << name() << ")" << x << std::endl; }, v1 ); + + std::variant v2( 2.0f ); + + std::cout << "(" << name() << ")v2: "; + std::visit( []( auto const& x ){ std::cout << "(" << name() << ")" << x << std::endl; }, v2 ); + + auto v3 = rvisit( []( auto const& x, auto const& y ){ return x + y; }, v1, v2 ); + + std::cout << "(" << name() << ")v3: "; + std::visit( []( auto const& x ){ std::cout << "(" << name() << ")" << x << std::endl; }, v3 ); + } + +[endsect] + +[endsect] diff --git a/doc/mp11/function.qbk b/doc/mp11/function.qbk new file mode 100644 index 0000000..01948c2 --- /dev/null +++ b/doc/mp11/function.qbk @@ -0,0 +1,40 @@ +[/ + / Copyright 2017 Peter Dimov + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:function Helper Metafunctions, ``] + +[section `mp_and`] + template using mp_and = /*...*/; + +`mp_and` is an alias for the first type `U` in `T...` for which `mp_to_bool` 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. +[endsect] + +[section `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 faster. +[endsect] + +[section `mp_or`] + template using mp_or = /*...*/; + +`mp_or` is an alias for the first type `U` in `T...` for which `mp_to_bool` 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. +[endsect] + +[section `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. +[endsect] + +[endsect] diff --git a/doc/mp11/integer_sequence.qbk b/doc/mp11/integer_sequence.qbk new file mode 100644 index 0000000..e33df75 --- /dev/null +++ b/doc/mp11/integer_sequence.qbk @@ -0,0 +1,45 @@ +[/ + / Copyright 2017 Peter Dimov + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:integer_sequence Integer Sequences, ``] + +The contents of this header are defined in namespace `boost`. + +[section `integer_sequence`] + template struct integer_sequence + { + }; + +`integer_sequence` holds a sequence of integers of type `T`. Same as C++14's `std::integer_sequence`. +[endsect] + +[section `make_integer_sequence`] + template using make_integer_sequence = /*...*/; + +`make_integer_sequence` is `integer_sequence`. Same as C++14's `std::make_integer_sequence`. +[endsect] + +[section `index_sequence`] + template using index_sequence = integer_sequence; + +`index_sequence` is an alias for `integer_sequence`. Same as C++14's `std::index_sequence`. +[endsect] + +[section `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`. +[endsect] + +[section `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`. +[endsect] + +[endsect] diff --git a/doc/mp11/integral.qbk b/doc/mp11/integral.qbk index 95f0260..77c45c8 100644 --- a/doc/mp11/integral.qbk +++ b/doc/mp11/integral.qbk @@ -8,6 +8,8 @@ [section:integral Integral Constants, ``] +For an Mp11 integral constant type `T`, `T::value` is an integral constant in the C++ sense. + [section `mp_bool`] template using mp_bool = std::integral_constant; [endsect] diff --git a/doc/mp11/overview.qbk b/doc/mp11/overview.qbk new file mode 100644 index 0000000..9c1389d --- /dev/null +++ b/doc/mp11/overview.qbk @@ -0,0 +1,33 @@ +[/ + / Copyright 2017 Peter Dimov + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[section Overview] + +Mp11 is a C++11 metaprogramming library based on template aliases and variadic templates. +It implements the approach outlined in the article +[@http://pdimov.com/cpp2/simple_cxx11_metaprogramming.html Simple C++11 metaprogramming] +([@http://pdimov.com/cpp2/simple_cxx11_metaprogramming_2.html part 2]). + +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>`. + +[endsect] diff --git a/doc/mp11/tuple_for_each.qbk b/doc/mp11/tuple_for_each.qbk new file mode 100644 index 0000000..bfdf767 --- /dev/null +++ b/doc/mp11/tuple_for_each.qbk @@ -0,0 +1,22 @@ +[/ + / Copyright 2017 Peter Dimov + / + / Distributed under the Boost Software License, Version 1.0. (See + / accompanying file LICENSE_1_0.txt or copy at + / http://www.boost.org/LICENSE_1_0.txt) + /] + +[section:tuple_for_each A "for each" algorithm for tuple-like types, ``] + +The contents of this header are defined in namespace `boost`. + +[section `tuple_for_each`] + 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` by evaluating the +expression `f(std::get(std::forward(tp)))` for `J` in 0..`N-1`, where `N` is `std::tuple_size>::value`. + +Returns `std::forward(f)`. +[endsect] + +[endsect] diff --git a/doc/mp11/utility.qbk b/doc/mp11/utility.qbk index 51c39d3..79c7c20 100644 --- a/doc/mp11/utility.qbk +++ b/doc/mp11/utility.qbk @@ -61,19 +61,20 @@ When `mp_valid` is `mp_true`, `mp_defer` is a struct with a ne `mp_defer` is an empty struct. [endsect] -[section `mp_quote`] - template class F> struct mp_quote +[section `mp_quote`] + template class F, class... T> struct mp_quote { - template using apply = F; + template using invoke = F; }; -`mp_quote` transforms the template `F` into a type. The nested template `apply` of the result is an alias for `F`. +`mp_quote` transforms the template `F` into a type. In the common case `mp_quote`, the nested template `invoke` of the result is an alias for `F`; +otherwise, `invoke` is an alias for `F`, allowing partial application. [endsect] -[section `mp_unquote`] - template using mp_unquote = typename Q::template apply; +[section `mp_invoke`] + template using mp_invoke = typename Q::template invoke; -`mp_unquote`, where `Q` is `mp_quote`, is an alias for `F`. +`mp_invoke` evaluates the nested template `invoke` of a quoted metafunction. `mp_invoke, T...>` is an alias for `F`. `mp_invoke, U...>` is an alias for `F`. [endsect] [endsect] diff --git a/include/boost/mp11/algorithm.hpp b/include/boost/mp11/algorithm.hpp index a25f48f..ac19959 100644 --- a/include/boost/mp11/algorithm.hpp +++ b/include/boost/mp11/algorithm.hpp @@ -23,6 +23,8 @@ namespace boost { +namespace mp11 +{ // mp_assign namespace detail @@ -490,15 +492,15 @@ template class L, class T1, class... T, template cl template class P> using mp_sort = typename detail::mp_sort_impl::type; -// mp_find_index +// mp_find namespace detail { -template struct mp_find_index_impl; +template struct mp_find_impl; #if !defined( BOOST_MP11_NO_CONSTEXPR ) -template class L, class V> struct mp_find_index_impl, V> +template class L, class V> struct mp_find_impl, V> { using type = mp_size_t<0>; }; @@ -508,7 +510,7 @@ constexpr std::size_t cx_find_index( bool const * first, bool const * last ) return first == last || *first? 0: 1 + cx_find_index( first + 1, last ); } -template class L, class... T, class V> struct mp_find_index_impl, V> +template class L, class... T, class V> struct mp_find_impl, V> { static constexpr bool _v[] = { std::is_same::value... }; using type = mp_size_t< cx_find_index( _v, _v + sizeof...(T) ) >; @@ -518,7 +520,7 @@ template class L, class... T, class V> struct mp_find_index_i #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 ) -template class L, class... T, class V> struct mp_find_index_impl, V> +template class L, class... T, class V> struct mp_find_impl, V> { static_assert( sizeof...(T) == 0, "T... must be empty" ); using type = mp_size_t<0>; @@ -526,21 +528,21 @@ template class L, class... T, class V> struct mp_find_index_i #else -template class L, class V> struct mp_find_index_impl, V> +template class L, class V> struct mp_find_impl, V> { using type = mp_size_t<0>; }; #endif -template class L, class... T, class V> struct mp_find_index_impl, V> +template class L, class... T, class V> struct mp_find_impl, V> { using type = mp_size_t<0>; }; -template class L, class T1, class... T, class V> struct mp_find_index_impl, V> +template class L, class T1, class... T, class V> struct mp_find_impl, V> { - using _r = typename mp_find_index_impl, V>::type; + using _r = typename mp_find_impl, V>::type; using type = mp_size_t<1 + _r::value>; }; @@ -548,22 +550,22 @@ template class L, class T1, class... T, class V> struct mp_fi } // namespace detail -template using mp_find_index = typename detail::mp_find_index_impl::type; +template using mp_find = typename detail::mp_find_impl::type; -// mp_find_index_if +// mp_find_if namespace detail { -template class P> struct mp_find_index_if_impl; +template class P> struct mp_find_if_impl; #if !defined( BOOST_MP11_NO_CONSTEXPR ) -template class L, template class P> struct mp_find_index_if_impl, P> +template class L, template class P> struct mp_find_if_impl, P> { using type = mp_size_t<0>; }; -template class L, class... T, template class P> struct mp_find_index_if_impl, P> +template class L, class... T, template class P> struct mp_find_if_impl, P> { static constexpr bool _v[] = { P::value... }; using type = mp_size_t< cx_find_index( _v, _v + sizeof...(T) ) >; @@ -573,7 +575,7 @@ template class L, class... T, template class P> str #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 ) -template class L, class... T, template class P> struct mp_find_index_if_impl, P> +template class L, class... T, template class P> struct mp_find_if_impl, P> { static_assert( sizeof...(T) == 0, "T... must be empty" ); using type = mp_size_t<0>; @@ -581,35 +583,29 @@ template class L, class... T, template class P> str #else -template class L, template class P> struct mp_find_index_if_impl, P> +template class L, template class P> struct mp_find_if_impl, P> { using type = mp_size_t<0>; }; #endif -template class P> struct mp_find_index_if_impl_2 +template class P> struct mp_find_if_impl_2 { - using _r = typename mp_find_index_if_impl::type; + using _r = typename mp_find_if_impl::type; using type = mp_size_t<1 + _r::value>; }; -template class L, class T1, class... T, template class P> struct mp_find_index_if_impl, P> +template class L, class T1, class... T, template class P> struct mp_find_if_impl, P> { - using type = typename mp_if, mp_identity>, mp_find_index_if_impl_2, P>>::type; + using type = typename mp_if, mp_identity>, mp_find_if_impl_2, P>>::type; }; #endif } // namespace detail -template class P> using mp_find_index_if = typename detail::mp_find_index_if_impl::type; - -// mp_find -template using mp_find = mp_drop>; - -// mp_find_if -template class P> using mp_find_if = mp_drop>; +template class P> using mp_find_if = typename detail::mp_find_if_impl::type; // mp_reverse namespace detail @@ -757,6 +753,7 @@ template class P> using mp_none_of = mp_bool< mp_cou // mp_any_of template class P> using mp_any_of = mp_bool< mp_count_if::value != 0 >; +} // namespace mp11 } // namespace boost #endif // #ifndef BOOST_MP11_ALGORITHM_HPP_INCLUDED diff --git a/include/boost/mp11/detail/mp_count.hpp b/include/boost/mp11/detail/mp_count.hpp index 782e5c6..c03128f 100644 --- a/include/boost/mp11/detail/mp_count.hpp +++ b/include/boost/mp11/detail/mp_count.hpp @@ -15,6 +15,8 @@ namespace boost { +namespace mp11 +{ // mp_count namespace detail @@ -87,6 +89,7 @@ template class L, class... T, template class P> str template class P> using mp_count_if = typename detail::mp_count_if_impl::type; +} // namespace mp11 } // namespace boost #endif // #ifndef BOOST_MP11_DETAIL_MP_COUNT_HPP_INCLUDED diff --git a/include/boost/mp11/detail/mp_list.hpp b/include/boost/mp11/detail/mp_list.hpp index e0e285a..8e8d3e5 100644 --- a/include/boost/mp11/detail/mp_list.hpp +++ b/include/boost/mp11/detail/mp_list.hpp @@ -10,12 +10,15 @@ namespace boost { +namespace mp11 +{ // mp_list template struct mp_list { }; +} // namespace mp11 } // namespace boost #endif // #ifndef BOOST_MP11_DETAIL_MP_LIST_HPP_INCLUDED diff --git a/include/boost/mp11/detail/mp_map_find.hpp b/include/boost/mp11/detail/mp_map_find.hpp index 6c01e45..ec0fabd 100644 --- a/include/boost/mp11/detail/mp_map_find.hpp +++ b/include/boost/mp11/detail/mp_map_find.hpp @@ -12,6 +12,8 @@ namespace boost { +namespace mp11 +{ // mp_map_find namespace detail @@ -35,6 +37,7 @@ template class M, class... T, class K> struct mp_map_find_imp template using mp_map_find = typename detail::mp_map_find_impl::type; +} // namespace mp11 } // namespace boost #endif // #ifndef BOOST_MP11_DETAIL_MP_MAP_FIND_HPP_INCLUDED diff --git a/include/boost/mp11/detail/mp_plus.hpp b/include/boost/mp11/detail/mp_plus.hpp index 88e34ef..c27e6de 100644 --- a/include/boost/mp11/detail/mp_plus.hpp +++ b/include/boost/mp11/detail/mp_plus.hpp @@ -13,6 +13,8 @@ namespace boost { +namespace mp11 +{ // mp_plus namespace detail @@ -41,6 +43,7 @@ template using mp_plus = typename detail::mp_plus_impl::type; +} // namespace mp11 } // namespace boost #endif // #ifndef BOOST_MP11_DETAIL_MP_PLUS_HPP_INCLUDED diff --git a/include/boost/mp11/function.hpp b/include/boost/mp11/function.hpp index cefec1a..e714aa0 100644 --- a/include/boost/mp11/function.hpp +++ b/include/boost/mp11/function.hpp @@ -1,7 +1,7 @@ #ifndef BOOST_MP11_FUNCTION_HPP_INCLUDED #define BOOST_MP11_FUNCTION_HPP_INCLUDED -// Copyright 2015, 2016 Peter Dimov. +// Copyright 2015-2017 Peter Dimov. // // Distributed under the Boost Software License, Version 1.0. // @@ -15,9 +15,8 @@ namespace boost { - -// mp_equal_to -template using mp_equal_to = mp_bool< T1::value == T2::value >; +namespace mp11 +{ // mp_all template using mp_all = mp_bool< mp_count_if< mp_list, mp_to_bool >::value == sizeof...(T) >; @@ -40,9 +39,14 @@ template<> struct mp_and_impl<> using type = mp_true; }; +template struct mp_and_impl +{ + using type = T; +}; + template struct mp_and_impl { - using type = mp_eval_if< mp_not, mp_false, mp_and, T... >; + using type = mp_eval_if< mp_not, T1, mp_and, T... >; }; } // namespace detail @@ -68,13 +72,19 @@ template<> struct mp_or_impl<> using type = mp_false; }; +template struct mp_or_impl +{ + using type = T; +}; + template struct mp_or_impl { - using type = mp_eval_if< T1, mp_true, mp_or, T... >; + using type = mp_eval_if< T1, T1, mp_or, T... >; }; } // namespace detail +} // namespace mp11 } // namespace boost #endif // #ifndef BOOST_MP11_FUNCTION_HPP_INCLUDED diff --git a/include/boost/mp11/integral.hpp b/include/boost/mp11/integral.hpp index ebe52b5..3e0ba19 100644 --- a/include/boost/mp11/integral.hpp +++ b/include/boost/mp11/integral.hpp @@ -13,6 +13,8 @@ namespace boost { +namespace mp11 +{ // mp_bool template using mp_bool = std::integral_constant; @@ -32,6 +34,7 @@ template using mp_int = std::integral_constant; // mp_size_t template using mp_size_t = std::integral_constant; +} // namespace mp11 } // namespace boost #endif // #ifndef BOOST_MP11_INTEGRAL_HPP_INCLUDED diff --git a/include/boost/mp11/list.hpp b/include/boost/mp11/list.hpp index 6f09d25..bb319d6 100644 --- a/include/boost/mp11/list.hpp +++ b/include/boost/mp11/list.hpp @@ -13,6 +13,8 @@ namespace boost { +namespace mp11 +{ // mp_size namespace detail @@ -168,6 +170,7 @@ template class L1, class... T1, template class L2, template using mp_append = typename detail::mp_append_impl::type; +} // namespace mp11 } // namespace boost #endif // #ifndef BOOST_MP11_LIST_HPP_INCLUDED diff --git a/include/boost/mp11/map.hpp b/include/boost/mp11/map.hpp index b12f48c..05778f1 100644 --- a/include/boost/mp11/map.hpp +++ b/include/boost/mp11/map.hpp @@ -17,6 +17,8 @@ namespace boost { +namespace mp11 +{ // mp_map_contains template using mp_map_contains = mp_not, void>>; @@ -77,6 +79,7 @@ template struct mp_map_erase_impl template using mp_map_erase = typename detail::mp_map_erase_impl::type; +} // namespace mp11 } // namespace boost #endif // #ifndef BOOST_MP11_MAP_HPP_INCLUDED diff --git a/include/boost/mp11/set.hpp b/include/boost/mp11/set.hpp index 568273a..a3b3b38 100644 --- a/include/boost/mp11/set.hpp +++ b/include/boost/mp11/set.hpp @@ -13,6 +13,8 @@ namespace boost { +namespace mp11 +{ // mp_set_contains namespace detail @@ -76,6 +78,7 @@ template class L, class... U, class T1, class... T> struct mp template using mp_set_push_front = typename detail::mp_set_push_front_impl::type; +} // namespace mp11 } // namespace boost #endif // #ifndef BOOST_MP11_SET_HPP_INCLUDED diff --git a/include/boost/mp11/utility.hpp b/include/boost/mp11/utility.hpp index a438a33..0f34d3f 100644 --- a/include/boost/mp11/utility.hpp +++ b/include/boost/mp11/utility.hpp @@ -1,7 +1,7 @@ #ifndef BOOST_MP11_UTILITY_HPP_INCLUDED #define BOOST_MP11_UTILITY_HPP_INCLUDED -// Copyright 2015 Peter Dimov. +// Copyright 2015, 2017 Peter Dimov. // // Distributed under the Boost Software License, Version 1.0. // @@ -12,6 +12,8 @@ namespace boost { +namespace mp11 +{ // mp_identity template struct mp_identity @@ -102,29 +104,30 @@ struct mp_no_type template class F, class... T> using mp_defer = mp_if, detail::mp_defer_impl, detail::mp_no_type>; // mp_quote -template class F> struct mp_quote +template class F, class... T> struct mp_quote { - template using apply = F; + template using invoke = F; }; // mp_unquote namespace detail { -template struct mp_unquote_impl +template struct mp_invoke_impl { - using type = typename Q::template apply; + using type = typename Q::template invoke; }; -template class F, class... T> struct mp_unquote_impl, T...> +template class F, class... T, class... U> struct mp_invoke_impl, U...> { - using type = F; + using type = F; }; } // namespace detail -template using mp_unquote = typename detail::mp_unquote_impl::type; +template using mp_invoke = typename detail::mp_invoke_impl::type; +} // namespace mp11 } // namespace boost #endif // #ifndef BOOST_MP11_UTILITY_HPP_INCLUDED diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index b00e64c..29c916b 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -48,8 +48,6 @@ run mp_remove.cpp : : : $(REQ) ; run mp_remove_if.cpp : : : $(REQ) ; run mp_partition.cpp : : : $(REQ) ; run mp_sort.cpp : : : $(REQ) ; -run mp_find_index.cpp : : : $(REQ) ; -run mp_find_index_if.cpp : : : $(REQ) ; run mp_find.cpp : : : $(REQ) ; run mp_find_if.cpp : : : $(REQ) ; run mp_reverse.cpp : : : $(REQ) ; @@ -71,6 +69,7 @@ run mp_eval_if.cpp : : : $(REQ) ; run mp_valid.cpp : : : $(REQ) ; run mp_defer.cpp : : : $(REQ) ; run mp_quote.cpp : : : $(REQ) ; +run mp_invoke.cpp : : : $(REQ) ; # integer_sequence run integer_sequence.cpp : : : $(REQ) ; diff --git a/test/integral.cpp b/test/integral.cpp index 82002b5..ce0f961 100644 --- a/test/integral.cpp +++ b/test/integral.cpp @@ -14,29 +14,29 @@ int main() { - using boost::mp_bool; + using boost::mp11::mp_bool; BOOST_TEST_TRAIT_TRUE((std::is_same, std::integral_constant>)); BOOST_TEST_TRAIT_TRUE((std::is_same, std::integral_constant>)); - using boost::mp_true; - using boost::mp_false; + using boost::mp11::mp_true; + using boost::mp11::mp_false; BOOST_TEST_TRAIT_TRUE((std::is_same>)); BOOST_TEST_TRAIT_TRUE((std::is_same>)); - using boost::mp_int; + using boost::mp11::mp_int; BOOST_TEST_TRAIT_TRUE((std::is_same, std::integral_constant>)); BOOST_TEST_TRAIT_TRUE((std::is_same, std::integral_constant>)); BOOST_TEST_TRAIT_TRUE((std::is_same, std::integral_constant>)); - using boost::mp_size_t; + using boost::mp11::mp_size_t; BOOST_TEST_TRAIT_TRUE((std::is_same, std::integral_constant>)); BOOST_TEST_TRAIT_TRUE((std::is_same, std::integral_constant>)); - using boost::mp_to_bool; + using boost::mp11::mp_to_bool; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_false>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_true>)); @@ -51,7 +51,7 @@ int main() BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_true>)); BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_true>)); - using boost::mp_not; + using boost::mp11::mp_not; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_true>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_false>)); diff --git a/test/mp_all.cpp b/test/mp_all.cpp index 651c208..6b5e2d7 100644 --- a/test/mp_all.cpp +++ b/test/mp_all.cpp @@ -14,11 +14,11 @@ int main() { - using boost::mp_all; - using boost::mp_true; - using boost::mp_false; - using boost::mp_int; - using boost::mp_size_t; + using boost::mp11::mp_all; + using boost::mp11::mp_true; + using boost::mp11::mp_false; + using boost::mp11::mp_int; + using boost::mp11::mp_size_t; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_true>)); diff --git a/test/mp_all_of.cpp b/test/mp_all_of.cpp index a19b18e..6e01aec 100644 --- a/test/mp_all_of.cpp +++ b/test/mp_all_of.cpp @@ -19,10 +19,10 @@ struct X1 {}; int main() { - using boost::mp_list; - using boost::mp_all_of; - using boost::mp_true; - using boost::mp_false; + using boost::mp11::mp_list; + using boost::mp11::mp_all_of; + using boost::mp11::mp_true; + using boost::mp11::mp_false; { using L1 = mp_list<>; diff --git a/test/mp_and.cpp b/test/mp_and.cpp index d75552f..0d3c00a 100644 --- a/test/mp_and.cpp +++ b/test/mp_and.cpp @@ -1,5 +1,5 @@ -// Copyright 2015, 2016 Peter Dimov. +// Copyright 2015-2017 Peter Dimov. // // Distributed under the Boost Software License, Version 1.0. // @@ -14,34 +14,34 @@ int main() { - using boost::mp_and; - using boost::mp_true; - using boost::mp_false; - using boost::mp_int; - using boost::mp_size_t; + using boost::mp11::mp_and; + using boost::mp11::mp_true; + using boost::mp11::mp_false; + using boost::mp11::mp_int; + using boost::mp11::mp_size_t; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_true>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_true>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_false>)); - BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_false>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_int<-7>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_int<0>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_false>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_size_t<7>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_size_t<0>>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_true>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_false>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_false>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<5>>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>>, mp_false>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, void>, mp_false>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<5>>, mp_int<5>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>>, mp_int<0>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, void>, mp_int<0>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<8>>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>, mp_false>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, void>, mp_false>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<8>>, mp_size_t<8>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>, mp_size_t<0>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, void>, mp_size_t<0>>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_true>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_false>)); @@ -54,11 +54,11 @@ int main() BOOST_TEST_TRAIT_TRUE((std::is_same, mp_false>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_false>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<2>, mp_int<-11>, mp_int<14>>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>, void, void>, mp_false>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<2>, mp_int<-11>, mp_int<14>>, mp_int<14>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>, void, void>, mp_int<0>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<2>, mp_size_t<114>, mp_size_t<8>, mp_size_t<94>>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<2>, mp_size_t<0>, void, void>, mp_false>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<2>, mp_size_t<114>, mp_size_t<8>, mp_size_t<94>>, mp_size_t<94>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<2>, mp_size_t<0>, void, void>, mp_size_t<0>>)); return boost::report_errors(); } diff --git a/test/mp_any.cpp b/test/mp_any.cpp index f7e45c9..9619522 100644 --- a/test/mp_any.cpp +++ b/test/mp_any.cpp @@ -14,11 +14,11 @@ int main() { - using boost::mp_any; - using boost::mp_true; - using boost::mp_false; - using boost::mp_int; - using boost::mp_size_t; + using boost::mp11::mp_any; + using boost::mp11::mp_true; + using boost::mp11::mp_false; + using boost::mp11::mp_int; + using boost::mp11::mp_size_t; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_false>)); diff --git a/test/mp_any_of.cpp b/test/mp_any_of.cpp index bcf3c19..e6aa3b1 100644 --- a/test/mp_any_of.cpp +++ b/test/mp_any_of.cpp @@ -19,10 +19,10 @@ struct X1 {}; int main() { - using boost::mp_list; - using boost::mp_any_of; - using boost::mp_true; - using boost::mp_false; + using boost::mp11::mp_list; + using boost::mp11::mp_any_of; + using boost::mp11::mp_true; + using boost::mp11::mp_false; { using L1 = mp_list<>; diff --git a/test/mp_append.cpp b/test/mp_append.cpp index cfe8e3f..25482c4 100644 --- a/test/mp_append.cpp +++ b/test/mp_append.cpp @@ -22,8 +22,8 @@ struct X6 {}; int main() { - using boost::mp_list; - using boost::mp_append; + using boost::mp11::mp_list; + using boost::mp11::mp_append; using L1 = mp_list; using L2 = mp_list; diff --git a/test/mp_assign.cpp b/test/mp_assign.cpp index cd6bea5..823607a 100644 --- a/test/mp_assign.cpp +++ b/test/mp_assign.cpp @@ -20,8 +20,8 @@ struct X3 {}; int main() { - using boost::mp_list; - using boost::mp_assign; + using boost::mp11::mp_list; + using boost::mp11::mp_assign; using L1 = mp_list; diff --git a/test/mp_at.cpp b/test/mp_at.cpp index ef22280..6ff3fd4 100644 --- a/test/mp_at.cpp +++ b/test/mp_at.cpp @@ -23,10 +23,10 @@ struct X5 {}; int main() { - using boost::mp_list; - using boost::mp_at; - using boost::mp_at_c; - using boost::mp_size_t; + using boost::mp11::mp_list; + using boost::mp11::mp_at; + using boost::mp11::mp_at_c; + using boost::mp11::mp_size_t; { using L1 = mp_list; diff --git a/test/mp_clear.cpp b/test/mp_clear.cpp index 991d5a5..3ecd530 100644 --- a/test/mp_clear.cpp +++ b/test/mp_clear.cpp @@ -16,8 +16,8 @@ int main() { - using boost::mp_list; - using boost::mp_clear; + using boost::mp11::mp_list; + using boost::mp11::mp_clear; using L1 = mp_list; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list<>>)); diff --git a/test/mp_contains.cpp b/test/mp_contains.cpp index deef491..04bfac6 100644 --- a/test/mp_contains.cpp +++ b/test/mp_contains.cpp @@ -21,10 +21,10 @@ struct X3 {}; int main() { - using boost::mp_list; - using boost::mp_contains; - using boost::mp_true; - using boost::mp_false; + using boost::mp11::mp_list; + using boost::mp11::mp_contains; + using boost::mp11::mp_true; + using boost::mp11::mp_false; { using L1 = mp_list<>; diff --git a/test/mp_copy_if.cpp b/test/mp_copy_if.cpp index d67f120..1545c18 100644 --- a/test/mp_copy_if.cpp +++ b/test/mp_copy_if.cpp @@ -19,8 +19,8 @@ struct X3 {}; int main() { - using boost::mp_list; - using boost::mp_copy_if; + using boost::mp11::mp_list; + using boost::mp11::mp_copy_if; { using L1 = mp_list<>; diff --git a/test/mp_count.cpp b/test/mp_count.cpp index 15c128a..41df7dd 100644 --- a/test/mp_count.cpp +++ b/test/mp_count.cpp @@ -21,9 +21,9 @@ struct X3 {}; int main() { - using boost::mp_list; - using boost::mp_count; - using boost::mp_size_t; + using boost::mp11::mp_list; + using boost::mp11::mp_count; + using boost::mp11::mp_size_t; { using L1 = mp_list<>; diff --git a/test/mp_count_if.cpp b/test/mp_count_if.cpp index 311cf12..ad728a9 100644 --- a/test/mp_count_if.cpp +++ b/test/mp_count_if.cpp @@ -19,9 +19,9 @@ struct X1 {}; int main() { - using boost::mp_list; - using boost::mp_count_if; - using boost::mp_size_t; + using boost::mp11::mp_list; + using boost::mp11::mp_count_if; + using boost::mp11::mp_size_t; { using L1 = mp_list<>; diff --git a/test/mp_defer.cpp b/test/mp_defer.cpp index e6fdbc7..492e32b 100644 --- a/test/mp_defer.cpp +++ b/test/mp_defer.cpp @@ -12,17 +12,21 @@ #include #include +using boost::mp11::mp_identity; +using boost::mp11::mp_true; +using boost::mp11::mp_false; + template struct has_type { - template static boost::mp_true f( boost::mp_identity* ); - template static boost::mp_false f( ... ); + template static mp_true f( mp_identity* ); + template static mp_false f( ... ); using type = decltype( f(0) ); static const auto value = type::value; }; -using boost::mp_defer; +using boost::mp11::mp_defer; template using add_pointer = T*; template using add_pointer_impl = mp_defer; diff --git a/test/mp_drop.cpp b/test/mp_drop.cpp index 6cadc27..186aa94 100644 --- a/test/mp_drop.cpp +++ b/test/mp_drop.cpp @@ -23,10 +23,10 @@ struct X5 {}; int main() { - using boost::mp_list; - using boost::mp_drop; - using boost::mp_drop_c; - using boost::mp_size_t; + using boost::mp11::mp_list; + using boost::mp11::mp_drop; + using boost::mp11::mp_drop_c; + using boost::mp11::mp_size_t; { using L1 = mp_list<>; diff --git a/test/mp_empty.cpp b/test/mp_empty.cpp index 7e137a8..87e0fb7 100644 --- a/test/mp_empty.cpp +++ b/test/mp_empty.cpp @@ -16,10 +16,10 @@ int main() { - using boost::mp_list; - using boost::mp_empty; - using boost::mp_true; - using boost::mp_false; + using boost::mp11::mp_list; + using boost::mp11::mp_empty; + using boost::mp11::mp_true; + using boost::mp11::mp_false; using L1 = mp_list<>; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_true>)); diff --git a/test/mp_eval_if.cpp b/test/mp_eval_if.cpp index 218b8d1..1c8ed39 100644 --- a/test/mp_eval_if.cpp +++ b/test/mp_eval_if.cpp @@ -14,23 +14,23 @@ int main() { - using boost::mp_eval_if_c; - using boost::mp_identity; + using boost::mp11::mp_eval_if_c; + using boost::mp11::mp_identity; BOOST_TEST_TRAIT_TRUE((std::is_same, char[]>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_identity>)); - using boost::mp_eval_if; + using boost::mp11::mp_eval_if; BOOST_TEST_TRAIT_TRUE((std::is_same, char[]>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_identity>)); - using boost::mp_int; + using boost::mp11::mp_int; BOOST_TEST_TRAIT_TRUE((std::is_same, char[], mp_identity, void, void, void>, char[]>)); BOOST_TEST_TRAIT_TRUE((std::is_same, char[], mp_identity, void()>, mp_identity>)); - using boost::mp_size_t; + using boost::mp11::mp_size_t; BOOST_TEST_TRAIT_TRUE((std::is_same, char[], mp_identity, void, void, void>, char[]>)); BOOST_TEST_TRAIT_TRUE((std::is_same, char[], mp_identity, void()>, mp_identity>)); diff --git a/test/mp_fill.cpp b/test/mp_fill.cpp index e12f538..1b5fc2e 100644 --- a/test/mp_fill.cpp +++ b/test/mp_fill.cpp @@ -18,8 +18,8 @@ struct X1 {}; int main() { - using boost::mp_list; - using boost::mp_fill; + using boost::mp11::mp_list; + using boost::mp11::mp_fill; using L1 = mp_list; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); diff --git a/test/mp_find.cpp b/test/mp_find.cpp index b9b3b2e..21aeb26 100644 --- a/test/mp_find.cpp +++ b/test/mp_find.cpp @@ -21,33 +21,42 @@ struct X3 {}; int main() { - using boost::mp_list; - using boost::mp_find; + using boost::mp11::mp_list; + using boost::mp11::mp_find; + using boost::mp11::mp_size_t; { using L1 = mp_list<>; - BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); using L2 = mp_list; - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list<>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<6>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<1>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<3>>)); } { using L3 = std::tuple<>; - BOOST_TEST_TRAIT_TRUE((std::is_same, L3>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); using L4 = std::tuple; - BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple<>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, L4>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<6>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<1>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<3>>)); + } + + { + using L5 = std::pair; + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<2>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<1>>)); } return boost::report_errors(); diff --git a/test/mp_find_if.cpp b/test/mp_find_if.cpp index 72fc9e0..6310390 100644 --- a/test/mp_find_if.cpp +++ b/test/mp_find_if.cpp @@ -19,31 +19,40 @@ struct X1 {}; int main() { - using boost::mp_list; - using boost::mp_find_if; + using boost::mp11::mp_list; + using boost::mp11::mp_find_if; + using boost::mp11::mp_size_t; { using L1 = mp_list<>; - BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); using L2 = mp_list; - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list<>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<6>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<1>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<3>>)); } { using L1 = std::tuple<>; - BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); using L2 = std::tuple; - BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple<>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<6>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<1>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<3>>)); + } + + { + using L2 = std::pair; + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<2>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<1>>)); } return boost::report_errors(); diff --git a/test/mp_find_index.cpp b/test/mp_find_index.cpp deleted file mode 100644 index 570f641..0000000 --- a/test/mp_find_index.cpp +++ /dev/null @@ -1,63 +0,0 @@ - -// Copyright 2015 Peter Dimov. -// -// Distributed under the Boost Software License, Version 1.0. -// -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt - - -#include -#include -#include -#include -#include -#include -#include - -struct X1 {}; -struct X2 {}; -struct X3 {}; - -int main() -{ - using boost::mp_list; - using boost::mp_find_index; - using boost::mp_size_t; - - { - using L1 = mp_list<>; - - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); - - using L2 = mp_list; - - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<6>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<1>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<3>>)); - } - - { - using L3 = std::tuple<>; - - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); - - using L4 = std::tuple; - - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<6>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<1>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<3>>)); - } - - { - using L5 = std::pair; - - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<2>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<1>>)); - } - - return boost::report_errors(); -} diff --git a/test/mp_find_index_if.cpp b/test/mp_find_index_if.cpp deleted file mode 100644 index 3544f0b..0000000 --- a/test/mp_find_index_if.cpp +++ /dev/null @@ -1,59 +0,0 @@ - -// Copyright 2015 Peter Dimov. -// -// Distributed under the Boost Software License, Version 1.0. -// -// See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt - - -#include -#include -#include -#include -#include -#include -#include - -struct X1 {}; - -int main() -{ - using boost::mp_list; - using boost::mp_find_index_if; - using boost::mp_size_t; - - { - using L1 = mp_list<>; - - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); - - using L2 = mp_list; - - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<6>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<1>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<3>>)); - } - - { - using L1 = std::tuple<>; - - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); - - using L2 = std::tuple; - - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<6>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<1>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<3>>)); - } - - { - using L2 = std::pair; - - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<2>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<1>>)); - } - - return boost::report_errors(); -} diff --git a/test/mp_fold.cpp b/test/mp_fold.cpp index eb5070a..4a0fa73 100644 --- a/test/mp_fold.cpp +++ b/test/mp_fold.cpp @@ -22,8 +22,8 @@ template struct F {}; int main() { - using boost::mp_list; - using boost::mp_fold; + using boost::mp11::mp_list; + using boost::mp11::mp_fold; { BOOST_TEST_TRAIT_TRUE((std::is_same, void, F>, void>)); @@ -41,13 +41,13 @@ int main() BOOST_TEST_TRAIT_TRUE((std::is_same, void, F>, F, X2>, X3>, X4>>)); } - using boost::mp_push_back; + using boost::mp11::mp_push_back; { BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list<>, mp_push_back>, mp_list>)); } - using boost::mp_push_front; + using boost::mp11::mp_push_front; { BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list<>, mp_push_front>, mp_list>)); diff --git a/test/mp_front.cpp b/test/mp_front.cpp index 90a0976..3edb856 100644 --- a/test/mp_front.cpp +++ b/test/mp_front.cpp @@ -15,9 +15,9 @@ int main() { - using boost::mp_list; - using boost::mp_front; - using boost::mp_first; + using boost::mp11::mp_list; + using boost::mp11::mp_front; + using boost::mp11::mp_first; using L1 = mp_list; BOOST_TEST_TRAIT_TRUE((std::is_same, void>)); diff --git a/test/mp_identity.cpp b/test/mp_identity.cpp index 46ce6a4..3198718 100644 --- a/test/mp_identity.cpp +++ b/test/mp_identity.cpp @@ -15,14 +15,14 @@ struct X {}; int main() { - using boost::mp_identity; + using boost::mp11::mp_identity; BOOST_TEST_TRAIT_TRUE((std::is_same::type, void const volatile>)); BOOST_TEST_TRAIT_TRUE((std::is_same::type, void()>)); BOOST_TEST_TRAIT_TRUE((std::is_same::type, int const[]>)); BOOST_TEST_TRAIT_TRUE((std::is_same::type, X>)); - using boost::mp_identity_t; + using boost::mp11::mp_identity_t; BOOST_TEST_TRAIT_TRUE((std::is_same, void const volatile>)); BOOST_TEST_TRAIT_TRUE((std::is_same, void()>)); diff --git a/test/mp_if.cpp b/test/mp_if.cpp index 88036f9..1a5bca9 100644 --- a/test/mp_if.cpp +++ b/test/mp_if.cpp @@ -14,22 +14,22 @@ int main() { - using boost::mp_if_c; + using boost::mp11::mp_if_c; BOOST_TEST_TRAIT_TRUE((std::is_same, char[]>)); BOOST_TEST_TRAIT_TRUE((std::is_same, void()>)); - using boost::mp_if; + using boost::mp11::mp_if; BOOST_TEST_TRAIT_TRUE((std::is_same, char[]>)); BOOST_TEST_TRAIT_TRUE((std::is_same, void()>)); - using boost::mp_int; + using boost::mp11::mp_int; BOOST_TEST_TRAIT_TRUE((std::is_same, char[], void()>, char[]>)); BOOST_TEST_TRAIT_TRUE((std::is_same, char[], void()>, void()>)); - using boost::mp_size_t; + using boost::mp11::mp_size_t; BOOST_TEST_TRAIT_TRUE((std::is_same, char[], void()>, char[]>)); BOOST_TEST_TRAIT_TRUE((std::is_same, char[], void()>, void()>)); diff --git a/test/mp_inherit.cpp b/test/mp_inherit.cpp index cf9ec09..dfd5fc4 100644 --- a/test/mp_inherit.cpp +++ b/test/mp_inherit.cpp @@ -17,7 +17,7 @@ struct X3 {}; int main() { - using boost::mp_inherit; + using boost::mp11::mp_inherit; BOOST_TEST_TRAIT_TRUE((std::is_base_of>)); BOOST_TEST_TRAIT_TRUE((std::is_base_of>)); diff --git a/test/mp_invoke.cpp b/test/mp_invoke.cpp new file mode 100644 index 0000000..16ec66e --- /dev/null +++ b/test/mp_invoke.cpp @@ -0,0 +1,56 @@ + +// Copyright 2015, 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + + +#include +#include +#include +#include + +using boost::mp11::mp_invoke; +using boost::mp11::mp_size_t; + +struct Q1 +{ + template using invoke = void; +}; + +struct Q2 +{ + template class invoke; +}; + +struct Q3 +{ + template using invoke = mp_size_t; +}; + +struct Q4 +{ + template using invoke = T1; +}; + +int main() +{ + BOOST_TEST_TRAIT_TRUE((std::is_same, void>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, void>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, void>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, Q2::invoke<>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Q2::invoke>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Q2::invoke>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<1>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<2>>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, int>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, int[]>)); + + return boost::report_errors(); +} diff --git a/test/mp_iota.cpp b/test/mp_iota.cpp index a1eadfc..044251d 100644 --- a/test/mp_iota.cpp +++ b/test/mp_iota.cpp @@ -14,11 +14,11 @@ int main() { - using boost::mp_list; - using boost::mp_iota; - using boost::mp_iota_c; - using boost::mp_int; - using boost::mp_size_t; + using boost::mp11::mp_list; + using boost::mp11::mp_iota; + using boost::mp11::mp_iota_c; + using boost::mp11::mp_int; + using boost::mp11::mp_size_t; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list<>>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>>)); diff --git a/test/mp_map_contains.cpp b/test/mp_map_contains.cpp index e9d36b2..777b5c8 100644 --- a/test/mp_map_contains.cpp +++ b/test/mp_map_contains.cpp @@ -17,10 +17,10 @@ int main() { - using boost::mp_map_contains; - using boost::mp_list; - using boost::mp_true; - using boost::mp_false; + using boost::mp11::mp_map_contains; + using boost::mp11::mp_list; + using boost::mp11::mp_true; + using boost::mp11::mp_false; BOOST_TEST_TRAIT_TRUE((std::is_same, char>, mp_false>)); BOOST_TEST_TRAIT_TRUE((std::is_same, int>, mp_false>)); diff --git a/test/mp_map_erase.cpp b/test/mp_map_erase.cpp index 466f4c9..db0c691 100644 --- a/test/mp_map_erase.cpp +++ b/test/mp_map_erase.cpp @@ -16,8 +16,8 @@ int main() { - using boost::mp_map_erase; - using boost::mp_list; + using boost::mp11::mp_map_erase; + using boost::mp11::mp_list; BOOST_TEST_TRAIT_TRUE((std::is_same, void>, mp_list<>>)); BOOST_TEST_TRAIT_TRUE((std::is_same, int>, std::tuple<>>)); diff --git a/test/mp_map_find.cpp b/test/mp_map_find.cpp index 6c26b9b..2bd614d 100644 --- a/test/mp_map_find.cpp +++ b/test/mp_map_find.cpp @@ -16,8 +16,8 @@ int main() { - using boost::mp_map_find; - using boost::mp_list; + using boost::mp11::mp_map_find; + using boost::mp11::mp_list; BOOST_TEST_TRAIT_TRUE((std::is_same, char>, void>)); BOOST_TEST_TRAIT_TRUE((std::is_same, int>, void>)); diff --git a/test/mp_map_insert.cpp b/test/mp_map_insert.cpp index b334c9f..11920a7 100644 --- a/test/mp_map_insert.cpp +++ b/test/mp_map_insert.cpp @@ -16,9 +16,9 @@ int main() { - using boost::mp_map_insert; - using boost::mp_list; - using boost::mp_push_back; + using boost::mp11::mp_map_insert; + using boost::mp11::mp_list; + using boost::mp11::mp_push_back; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>, mp_list>>)); BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>, std::tuple>>)); diff --git a/test/mp_map_replace.cpp b/test/mp_map_replace.cpp index 416a0fb..c68b059 100644 --- a/test/mp_map_replace.cpp +++ b/test/mp_map_replace.cpp @@ -16,9 +16,9 @@ int main() { - using boost::mp_map_replace; - using boost::mp_list; - using boost::mp_push_back; + using boost::mp11::mp_map_replace; + using boost::mp11::mp_list; + using boost::mp11::mp_push_back; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>, mp_list>>)); BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>, std::tuple>>)); diff --git a/test/mp_map_update.cpp b/test/mp_map_update.cpp index 0069072..24e7e77 100644 --- a/test/mp_map_update.cpp +++ b/test/mp_map_update.cpp @@ -15,14 +15,14 @@ #include #include -using boost::mp_int; +using boost::mp11::mp_int; template using inc = mp_int; int main() { - using boost::mp_map_update; - using boost::mp_list; + using boost::mp11::mp_map_update; + using boost::mp11::mp_list; using M1 = mp_list<>; diff --git a/test/mp_none_of.cpp b/test/mp_none_of.cpp index 1ee4099..c0bd37e 100644 --- a/test/mp_none_of.cpp +++ b/test/mp_none_of.cpp @@ -19,10 +19,10 @@ struct X1 {}; int main() { - using boost::mp_list; - using boost::mp_none_of; - using boost::mp_true; - using boost::mp_false; + using boost::mp11::mp_list; + using boost::mp11::mp_none_of; + using boost::mp11::mp_true; + using boost::mp11::mp_false; { using L1 = mp_list<>; diff --git a/test/mp_or.cpp b/test/mp_or.cpp index 3e4c842..24190cf 100644 --- a/test/mp_or.cpp +++ b/test/mp_or.cpp @@ -1,5 +1,5 @@ -// Copyright 2015, 2016 Peter Dimov. +// Copyright 2015-2017 Peter Dimov. // // Distributed under the Boost Software License, Version 1.0. // @@ -14,34 +14,34 @@ int main() { - using boost::mp_or; - using boost::mp_true; - using boost::mp_false; - using boost::mp_int; - using boost::mp_size_t; + using boost::mp11::mp_or; + using boost::mp11::mp_true; + using boost::mp11::mp_false; + using boost::mp11::mp_int; + using boost::mp11::mp_size_t; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_false>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_true>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_false>)); - BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_false>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_int<-7>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_int<0>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_false>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_size_t<7>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_size_t<0>>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_true>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_true>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_false>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>>, mp_false>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<5>>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, void>, mp_true>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>>, mp_int<0>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<5>>, mp_int<5>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, void>, mp_int<-4>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, void>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<4>>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>, mp_false>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, void>, mp_size_t<7>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<4>>, mp_size_t<4>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>, mp_size_t<0>>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_true>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_true>)); @@ -54,19 +54,19 @@ int main() BOOST_TEST_TRAIT_TRUE((std::is_same, mp_true>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_false>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, void, void, void>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<2>, void, void, void>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>, mp_int<3>, void, void, void>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>, mp_int<0>, mp_int<4>, void, void, void>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>, mp_int<0>, mp_int<0>, mp_int<0>>, mp_false>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, void, void, void>, mp_int<1>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<2>, void, void, void>, mp_int<2>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>, mp_int<3>, void, void, void>, mp_int<3>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>, mp_int<0>, mp_int<4>, void, void, void>, mp_int<4>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>, mp_int<0>, mp_int<0>, mp_int<0>>, mp_int<0>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, void, void, void>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<2>, void, void, void>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>, mp_size_t<3>, void, void, void>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>, mp_size_t<0>, mp_size_t<4>, void, void, void>, mp_true>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>, mp_size_t<0>, mp_size_t<0>, mp_size_t<0>>, mp_false>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, void, void, void>, mp_size_t<1>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<2>, void, void, void>, mp_size_t<2>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>, mp_size_t<3>, void, void, void>, mp_size_t<3>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>, mp_size_t<0>, mp_size_t<4>, void, void, void>, mp_size_t<4>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>, mp_size_t<0>, mp_size_t<0>, mp_size_t<0>>, mp_size_t<0>>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>, mp_false, mp_size_t<141>, void, void, void>, mp_true>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>, mp_false, mp_size_t<141>, void, void, void>, mp_size_t<141>>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>, mp_false>, mp_false>)); return boost::report_errors(); diff --git a/test/mp_partition.cpp b/test/mp_partition.cpp index 461645e..8dc1ac2 100644 --- a/test/mp_partition.cpp +++ b/test/mp_partition.cpp @@ -19,8 +19,8 @@ struct X3 {}; int main() { - using boost::mp_list; - using boost::mp_partition; + using boost::mp11::mp_list; + using boost::mp11::mp_partition; { using L1 = mp_list<>; diff --git a/test/mp_pop_front.cpp b/test/mp_pop_front.cpp index f92dce9..f1ff16a 100644 --- a/test/mp_pop_front.cpp +++ b/test/mp_pop_front.cpp @@ -15,9 +15,9 @@ int main() { - using boost::mp_list; - using boost::mp_pop_front; - using boost::mp_rest; + using boost::mp11::mp_list; + using boost::mp11::mp_pop_front; + using boost::mp11::mp_rest; using L1 = mp_list; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list<>>)); diff --git a/test/mp_product.cpp b/test/mp_product.cpp index 351ea38..696965b 100644 --- a/test/mp_product.cpp +++ b/test/mp_product.cpp @@ -27,8 +27,8 @@ template struct F {}; int main() { - using boost::mp_list; - using boost::mp_product; + using boost::mp11::mp_list; + using boost::mp11::mp_product; { using L1 = std::tuple; diff --git a/test/mp_push_back.cpp b/test/mp_push_back.cpp index 6bd1935..c74fb03 100644 --- a/test/mp_push_back.cpp +++ b/test/mp_push_back.cpp @@ -15,8 +15,8 @@ int main() { - using boost::mp_list; - using boost::mp_push_back; + using boost::mp11::mp_list; + using boost::mp11::mp_push_back; using L1 = mp_list<>; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list<>>)); diff --git a/test/mp_push_front.cpp b/test/mp_push_front.cpp index 303fddc..73fcc8b 100644 --- a/test/mp_push_front.cpp +++ b/test/mp_push_front.cpp @@ -15,8 +15,8 @@ int main() { - using boost::mp_list; - using boost::mp_push_front; + using boost::mp11::mp_list; + using boost::mp11::mp_push_front; using L1 = mp_list<>; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list<>>)); diff --git a/test/mp_quote.cpp b/test/mp_quote.cpp index 74a8193..f05a91f 100644 --- a/test/mp_quote.cpp +++ b/test/mp_quote.cpp @@ -1,5 +1,5 @@ -// Copyright 2015 Peter Dimov. +// Copyright 2015, 2017 Peter Dimov. // // Distributed under the Boost Software License, Version 1.0. // @@ -11,18 +11,76 @@ #include #include -struct X {}; +using boost::mp11::mp_invoke; + +template struct X {}; + +template class F, class... T> using Y = X...>; + +template using Z = X...>; + +struct B {}; +struct D1: B {}; +struct D2: B {}; +struct ND {}; + +template using is_base_of_t = typename std::is_base_of::type; int main() { - using boost::mp_identity_t; - using boost::mp_quote; - using boost::mp_unquote; + using boost::mp11::mp_identity_t; + using boost::mp11::mp_quote; - using Q = mp_quote; + { + using Q = mp_quote; - BOOST_TEST_TRAIT_TRUE((std::is_same, void>)); - BOOST_TEST_TRAIT_TRUE((std::is_same, int[]>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, void>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, int[]>)); + } + + { + using Q = mp_quote; + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::is_same>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::is_same>)); + } + + { + using Q = mp_quote; + + BOOST_TEST_TRAIT_TRUE((std::is_same, X>)); + } + + { + using Q = mp_quote; + + // using R1 = Y; + // BOOST_TEST_TRAIT_TRUE((std::is_same>)); + // + // error: pack expansion used as argument for non-pack parameter of alias template + +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 && BOOST_MSVC >= 1900 ) +#else + using R2 = Z; + BOOST_TEST_TRAIT_TRUE((std::is_same>)); +#endif + } + + { + using Q = mp_quote; + +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 ) +#else + using R1 = Y; + BOOST_TEST_TRAIT_TRUE((std::is_same>)); +#endif + +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 && BOOST_MSVC >= 1900 ) +#else + using R2 = Z; + BOOST_TEST_TRAIT_TRUE((std::is_same>)); +#endif + } return boost::report_errors(); } diff --git a/test/mp_remove.cpp b/test/mp_remove.cpp index 8daff77..87d9c61 100644 --- a/test/mp_remove.cpp +++ b/test/mp_remove.cpp @@ -19,8 +19,8 @@ struct X3 {}; int main() { - using boost::mp_list; - using boost::mp_remove; + using boost::mp11::mp_list; + using boost::mp11::mp_remove; { using L1 = mp_list<>; diff --git a/test/mp_remove_if.cpp b/test/mp_remove_if.cpp index f1fdfc9..733f9fb 100644 --- a/test/mp_remove_if.cpp +++ b/test/mp_remove_if.cpp @@ -19,8 +19,8 @@ struct X3 {}; int main() { - using boost::mp_list; - using boost::mp_remove_if; + using boost::mp11::mp_list; + using boost::mp11::mp_remove_if; { using L1 = mp_list<>; diff --git a/test/mp_rename.cpp b/test/mp_rename.cpp index c0f3b60..e124683 100644 --- a/test/mp_rename.cpp +++ b/test/mp_rename.cpp @@ -18,8 +18,8 @@ template using Y = X; int main() { - using boost::mp_list; - using boost::mp_rename; + using boost::mp11::mp_list; + using boost::mp11::mp_rename; using L1 = mp_list<>; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list<>>)); diff --git a/test/mp_repeat.cpp b/test/mp_repeat.cpp index a145fc8..574b4fe 100644 --- a/test/mp_repeat.cpp +++ b/test/mp_repeat.cpp @@ -20,13 +20,13 @@ struct X2 {}; int main() { - using boost::mp_list; - using boost::mp_repeat; - using boost::mp_repeat_c; - using boost::mp_true; - using boost::mp_false; - using boost::mp_int; - using boost::mp_size_t; + using boost::mp11::mp_list; + using boost::mp11::mp_repeat; + using boost::mp11::mp_repeat_c; + using boost::mp11::mp_true; + using boost::mp11::mp_false; + using boost::mp11::mp_int; + using boost::mp11::mp_size_t; using L1 = mp_list<>; diff --git a/test/mp_replace.cpp b/test/mp_replace.cpp index 9562bfe..36a0ac6 100644 --- a/test/mp_replace.cpp +++ b/test/mp_replace.cpp @@ -20,8 +20,8 @@ struct X3 {}; int main() { - using boost::mp_list; - using boost::mp_replace; + using boost::mp11::mp_list; + using boost::mp11::mp_replace; { using L1 = mp_list<>; diff --git a/test/mp_replace_if.cpp b/test/mp_replace_if.cpp index c075494..98845d3 100644 --- a/test/mp_replace_if.cpp +++ b/test/mp_replace_if.cpp @@ -18,8 +18,8 @@ struct X1 {}; int main() { - using boost::mp_list; - using boost::mp_replace_if; + using boost::mp11::mp_list; + using boost::mp11::mp_replace_if; { using L1 = mp_list<>; diff --git a/test/mp_reverse.cpp b/test/mp_reverse.cpp index 740716c..79d7cb6 100644 --- a/test/mp_reverse.cpp +++ b/test/mp_reverse.cpp @@ -25,8 +25,8 @@ struct X9 {}; int main() { - using boost::mp_list; - using boost::mp_reverse; + using boost::mp11::mp_list; + using boost::mp11::mp_reverse; { BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list<>>)); diff --git a/test/mp_reverse_fold.cpp b/test/mp_reverse_fold.cpp index d646a11..f88b645 100644 --- a/test/mp_reverse_fold.cpp +++ b/test/mp_reverse_fold.cpp @@ -20,13 +20,16 @@ struct X4 {}; template struct F {}; -template using rev_push_back = boost::mp_push_back; -template using rev_push_front = boost::mp_push_front; +using boost::mp11::mp_push_back; +using boost::mp11::mp_push_front; + +template using rev_push_back = mp_push_back; +template using rev_push_front = mp_push_front; int main() { - using boost::mp_list; - using boost::mp_reverse_fold; + using boost::mp11::mp_list; + using boost::mp11::mp_reverse_fold; { BOOST_TEST_TRAIT_TRUE((std::is_same, void, F>, void>)); diff --git a/test/mp_second.cpp b/test/mp_second.cpp index 202a18f..f585bea 100644 --- a/test/mp_second.cpp +++ b/test/mp_second.cpp @@ -15,8 +15,8 @@ int main() { - using boost::mp_list; - using boost::mp_second; + using boost::mp11::mp_list; + using boost::mp11::mp_second; using L1 = mp_list; BOOST_TEST_TRAIT_TRUE((std::is_same, char[]>)); diff --git a/test/mp_set_contains.cpp b/test/mp_set_contains.cpp index adc97d6..d533146 100644 --- a/test/mp_set_contains.cpp +++ b/test/mp_set_contains.cpp @@ -16,10 +16,10 @@ int main() { - using boost::mp_list; - using boost::mp_set_contains; - using boost::mp_true; - using boost::mp_false; + using boost::mp11::mp_list; + using boost::mp11::mp_set_contains; + using boost::mp11::mp_true; + using boost::mp11::mp_false; { using L1 = mp_list<>; diff --git a/test/mp_set_push_back.cpp b/test/mp_set_push_back.cpp index f39cfbb..0855536 100644 --- a/test/mp_set_push_back.cpp +++ b/test/mp_set_push_back.cpp @@ -15,8 +15,8 @@ int main() { - using boost::mp_list; - using boost::mp_set_push_back; + using boost::mp11::mp_list; + using boost::mp11::mp_set_push_back; { using L1 = mp_list<>; diff --git a/test/mp_set_push_front.cpp b/test/mp_set_push_front.cpp index 3c33c41..a027ac3 100644 --- a/test/mp_set_push_front.cpp +++ b/test/mp_set_push_front.cpp @@ -15,8 +15,8 @@ int main() { - using boost::mp_list; - using boost::mp_set_push_front; + using boost::mp11::mp_list; + using boost::mp11::mp_set_push_front; { using L1 = mp_list<>; diff --git a/test/mp_size.cpp b/test/mp_size.cpp index ae8969c..a8ea75f 100644 --- a/test/mp_size.cpp +++ b/test/mp_size.cpp @@ -16,9 +16,9 @@ int main() { - using boost::mp_list; - using boost::mp_size; - using boost::mp_size_t; + using boost::mp11::mp_list; + using boost::mp11::mp_size; + using boost::mp11::mp_size_t; using L1 = mp_list<>; BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); diff --git a/test/mp_sort.cpp b/test/mp_sort.cpp index d339d29..d6b677f 100644 --- a/test/mp_sort.cpp +++ b/test/mp_sort.cpp @@ -14,14 +14,14 @@ #include #include -using boost::mp_bool; +using boost::mp11::mp_bool; template using sizeof_less = mp_bool<(sizeof(T) < sizeof(U))>; int main() { - using boost::mp_list; - using boost::mp_sort; + using boost::mp11::mp_list; + using boost::mp11::mp_sort; { using L1 = mp_list<>; diff --git a/test/mp_take.cpp b/test/mp_take.cpp index eac3f12..6648ccf 100644 --- a/test/mp_take.cpp +++ b/test/mp_take.cpp @@ -23,10 +23,10 @@ struct X5 {}; int main() { - using boost::mp_list; - using boost::mp_take; - using boost::mp_take_c; - using boost::mp_size_t; + using boost::mp11::mp_list; + using boost::mp11::mp_take; + using boost::mp11::mp_take_c; + using boost::mp11::mp_size_t; { using L1 = mp_list<>; diff --git a/test/mp_third.cpp b/test/mp_third.cpp index 75ad293..c43b85d 100644 --- a/test/mp_third.cpp +++ b/test/mp_third.cpp @@ -15,8 +15,8 @@ int main() { - using boost::mp_list; - using boost::mp_third; + using boost::mp11::mp_list; + using boost::mp11::mp_third; using L1 = mp_list; BOOST_TEST_TRAIT_TRUE((std::is_same, float[]>)); diff --git a/test/mp_transform.cpp b/test/mp_transform.cpp index 3d17a16..6782278 100644 --- a/test/mp_transform.cpp +++ b/test/mp_transform.cpp @@ -34,8 +34,8 @@ template using is_same = typename std::is_same::type; int main() { - using boost::mp_list; - using boost::mp_transform; + using boost::mp11::mp_list; + using boost::mp11::mp_transform; using L1 = mp_list; diff --git a/test/mp_transform_if.cpp b/test/mp_transform_if.cpp index 99b6bb7..0151ac5 100644 --- a/test/mp_transform_if.cpp +++ b/test/mp_transform_if.cpp @@ -20,13 +20,15 @@ struct X2 {}; struct X3 {}; struct X4 {}; +using boost::mp11::mp_not; + template using add_pointer = T*; -template using is_not_ref = boost::mp_not>; +template using is_not_ref = mp_not>; int main() { - using boost::mp_list; - using boost::mp_transform_if; + using boost::mp11::mp_list; + using boost::mp11::mp_transform_if; using L1 = mp_list; diff --git a/test/mp_unique.cpp b/test/mp_unique.cpp index cdc2f98..697d4ce 100644 --- a/test/mp_unique.cpp +++ b/test/mp_unique.cpp @@ -15,8 +15,8 @@ int main() { - using boost::mp_list; - using boost::mp_unique; + using boost::mp11::mp_list; + using boost::mp11::mp_unique; { BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list<>>)); diff --git a/test/mp_valid.cpp b/test/mp_valid.cpp index ed11ed1..a096442 100644 --- a/test/mp_valid.cpp +++ b/test/mp_valid.cpp @@ -27,8 +27,8 @@ template using add_extents = T[]; int main() { - using boost::mp_valid; - using boost::mp_identity; + using boost::mp11::mp_valid; + using boost::mp11::mp_identity; BOOST_TEST_TRAIT_FALSE((mp_valid)); BOOST_TEST_TRAIT_TRUE((mp_valid));