From 29a771aa4eacc065af6bf133364621360cf56223 Mon Sep 17 00:00:00 2001
From: Peter Dimov mp_bind_back_q<Q, T...>
<boost/integer_sequence.hpp>
<boost/mp11/integer_sequence.hpp>
integer_sequence<T, I...>
make_integer_sequence<T, N>
index_sequence_for<T...>
<boost/tuple_for_each.hpp>
<boost/mp11/tuple_for_each.hpp>
#include <boost/mp11.hpp> -#include <boost/tuple_for_each.hpp> #include <boost/core/demangle.hpp> #include <type_traits> #include <iostream> @@ -369,7 +368,7 @@ 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); } ); + tuple_for_each( mp_product<mp_list, L, L>(), [](auto&& x){ test_result(x); } ); }
@@ -871,8 +870,7 @@ Reference
- The contents of the library are in namespace boost::mp11
, unless
- specified otherwise.
+ The contents of the library are in namespace boost::mp11
.
- The contents of this header are defined in namespace boost
.
-
integer_sequence<T, I...>
@@ -2401,12 +2396,9 @@
- The contents of this header are defined in namespace boost
.
-
tuple_for_each
@@ -2429,7 +2421,7 @@
Last revised: May 22, 2017 at 13:46:31 GMT |
+Last revised: May 23, 2017 at 17:21:43 GMT |
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>>; +template<class T> using promote = typename std::common_type<T, int>::type; +template<class T, class U> using result = typename std::common_type<promote<T>, promote<U>>::type;that ought to represent the result of an arithmetic operation on the integer @@ -353,8 +353,8 @@ 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 T> using promote = typename std::common_type<T, int>::type; +template<class T, class U> using result = typename std::common_type<promote<T>, promote<U>>::type; template<class T1, class T2> void test_result( mp_list<T1, T2> const& ) { @@ -396,11 +396,33 @@
We then default-construct this tuple and pass it to
+tuple_for_each
.tuple_for_each(tp, f)
callsf
- for every tuple element; we use a (C++14) lambda that callstest_result
. (In pure C++11, we'd need - to maketest_result
a function - object with a templatedoperator()
and pass that totuple_for_each
- directly.) + for every tuple element; we use a (C++14) lambda that callstest_result
.+ In pure C++11, we can't use a lambda with an
+auto&&
parameter, so we'll have to make +test_result
a function object + with a templatedoperator()
+ and pass that totuple_for_each
+ directly: +struct test_result +{ + template<class T1, class T2> void operator()( mp_list<T1, T2> const& ) const + { + using T3 = decltype( T1() + T2() ); + using T4 = result<T1, T2>; + + std::cout << ( std::is_same<T3, T4>::value? "[PASS] ": "[FAIL] " ) + << name<T1>() << " + " << name<T2>() << " -> " << name<T3>() << ", result: " << name<T4>() << std::endl; + } +}; + +int main() +{ + using L = std::tuple<char, short, int, unsigned, long, unsigned long>; + tuple_for_each( mp_product<mp_list, L, L>(), test_result() ); +} +
std::common_type
to each pair of elements and gathers the results into a tuple:
-template<class Tp1, class Tp2> using common_tuple = mp_transform<std::common_type_t, Tp1, Tp2>; +template<class... T> using common_type_t = typename std::common_type<T...>::type; // standard in C++14 + +template<class Tp1, class Tp2> using common_tuple = mp_transform<common_type_t, Tp1, Tp2>;then specialize
common_type
@@ -463,16 +487,15 @@ E2, E3> andexpected<T2, E1, E4, E5>
- isexpected<std::common_type_t<T1, T2>, - E1, E2, E3, E4, - E5>
. - That is, the possible return values are combined into their common type, - and we take the union of the set of error types. + isexpected<common_type_t<T1, T2>, E1, E2, + E3, E4, E5>
. That is, the possible return values + are combined into their common type, and we take the union of the set of + error types.Therefore,
-template<class T1, class E1, class T2, class E2> using common_expected = mp_rename<mp_push_front<mp_unique<mp_append<E1, E2>>, std::common_type_t<T1, T2>>, expected>; +template<class T1, class E1, class T2, class E2> using common_expected = mp_rename<mp_push_front<mp_unique<mp_append<E1, E2>>, common_type_t<T1, T2>>, expected>; namespace std { @@ -491,7 +514,7 @@ This makes our job easier.mp_unique<mp_append<E1, E2>>
gives us the concatenation ofE1
andE2
with the duplicates - removed; we then addstd::common_type_t<T1, T2>
+ removed; we then addcommon_type_t<T1, T2>
to the front viamp_push_front
; and finally, wemp_rename
the resultantmp_list
to @@ -2421,7 +2444,7 @@
Last revised: May 23, 2017 at 17:21:43 GMT |
+Last revised: May 23, 2017 at 17:37:57 GMT |
mp_and<T...>
- is an alias for the first type U
+ is an alias for mp_false
+ if there exists a 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.
+ is mp_false
. mp_to_bool<U>
+ is not evaluated for types after U
.
+ If no such type exists, mp_and<T...>
is an alias for mp_true
.
+ (mp_and<>
+ is mp_true
.)
void
does
not have a nested value
.
The upside is that mp_all
- is faster.
+ is faster on legacy compilers.
mp_or<T...>
- is an alias for the first type U
+ is an alias for mp_true
+ if there exists a 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.
+ is mp_true
. mp_to_bool<U>
+ is not evaluated for types after U
.
+ If no such type exists, mp_or<T...>
is an alias for mp_false
.
+ (mp_or<>
+ is mp_false
.)
Last revised: May 23, 2017 at 17:37:57 GMT |
+Last revised: May 23, 2017 at 20:23:39 GMT |
<boost/mp11/function.hpp>
mp_void<T...>
mp_and<T...>
mp_all<T...>
mp_or<T...>
template<class... T> using mp_void = void; ++
+ Same as std::void_t
from C++17.
+
template<class... T> using mp_and = /*...*/; @@ -2168,12 +2179,17 @@ if there exists a typeU
inT...
for whichmp_to_bool<U>
- ismp_false
.mp_to_bool<U>
+ is notmp_true
.mp_to_bool<U>
is not evaluated for types afterU
. If no such type exists,mp_and<T...>
is an alias formp_true
. (mp_and<>
ismp_true
.) +using R1 = mp_and<mp_true, mp_true>; // mp_true +using R2 = mp_and<mp_false, void>; // mp_false, void is not reached +using R3 = mp_and<mp_false, mp_false>; // mp_false +using R4 = mp_and<void, mp_true>; // mp_false (!) +
mp_all
is faster on legacy compilers.
+using R1 = mp_and<mp_true, mp_true>; // mp_true +using R2 = mp_and<mp_false, void>; // compile-time error +using R3 = mp_and<mp_false, mp_false>; // mp_false +using R4 = mp_and<void, mp_true>; // compile-time error +
mp_or<T...>
- is an alias for mp_true
- if there exists a type U
- in T...
- for which mp_to_bool<U>
- is mp_true
. mp_to_bool<U>
- is not evaluated for types after U
.
- If no such type exists, mp_or<T...>
is an alias for mp_false
.
- (mp_or<>
- is mp_false
.)
+ applies mp_to_bool
to the
+ types in T...
,
+ in order. If the result of an application is mp_true
,
+ mp_or
returns mp_true
. If all results are mp_false
, returns mp_false
.
+ mp_or<>
+ is mp_false
.
using R1 = mp_or<mp_true, mp_false>; // mp_true +using R2 = mp_or<mp_true, void>; // mp_true, void is not reached +using R3 = mp_or<mp_false, mp_false>; // mp_false +using R4 = mp_or<void, mp_true>; // compile-time error +
mp_or
,
but does not perform short-circuit evaluation.
+using R1 = mp_any<mp_true, mp_false>; // mp_true +using R2 = mp_any<mp_true, void>; // compile-time error +using R3 = mp_any<mp_false, mp_false>; // mp_false +using R4 = mp_any<void, mp_true>; // compile-time error +
Last revised: May 23, 2017 at 20:23:39 GMT |
+Last revised: May 23, 2017 at 22:20:27 GMT |
mp_or<T...>
mp_any<T...>
mp_same<T...>
mp_plus<T...>
<boost/mp11/bind.hpp>
mp_true
.
template<class... T> using mp_plus = /*...*/; ++
+ mp_plus<T...>
+ is an integral constant type with a value that is the sum of U::value
+ for all types U
in T...
.
+ mp_plus<>
+ is mp_int<0>
.
+
Last revised: May 23, 2017 at 22:20:27 GMT |
+Last revised: May 23, 2017 at 22:51:13 GMT |
mp_and<T...>
- is an alias for mp_false
- if there exists a type U
- in T...
- for which mp_to_bool<U>
- is not mp_true
. mp_to_bool<U>
- is not evaluated for types after U
.
- If no such type exists, mp_and<T...>
is an alias for mp_true
.
- (mp_and<>
- is mp_true
.)
+ applies mp_to_bool
to the
+ types in T...
,
+ in order. If the result of an application is mp_false
,
+ mp_and
returns mp_false
. If the application causes a
+ substitution failure, returns mp_false
.
+ If all results are mp_true
,
+ returns mp_true
. mp_and<>
+ is mp_true
.
using R1 = mp_and<mp_true, mp_true>; // mp_true using R2 = mp_and<mp_false, void>; // mp_false, void is not reached @@ -2209,7 +2208,7 @@ is an error becausevoid
does not have a nestedvalue
. The upside is thatmp_all
- is faster on legacy compilers. + is potentially faster and does not mask substitution failures asmp_and
does.using R1 = mp_and<mp_true, mp_true>; // mp_true using R2 = mp_and<mp_false, void>; // compile-time error @@ -2493,7 +2492,7 @@
Last revised: May 23, 2017 at 22:51:13 GMT |
+Last revised: May 24, 2017 at 02:43:53 GMT |