diff --git a/doc/html/mp11.html b/doc/html/mp11.html index cd95a45..b5bbe7b 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -109,6 +109,7 @@
mp_repeat_c<L, N>
mp_repeat<L, N>
mp_product<F, L...>
+
mp_product_q<Q, L...>
mp_drop_c<L, N>
mp_drop<L, N>
mp_iota_c<N>
@@ -118,6 +119,10 @@ I>
mp_take_c<L, N>
mp_take<L, N>
+
mp_insert_c<L, I, T...>
+
mp_insert<L, I, T...>
+
mp_erase_c<L, I, J>
+
mp_erase<L, I, J>
mp_replace<L, V, W>
mp_replace_if<L, P, W>
mp_replace_at_c<L, I, W>
@@ -136,6 +141,7 @@
mp_all_of<L, P>
mp_none_of<L, P>
mp_any_of<L, P>
+
mp_for_each<L>(f)
Set Operations, <boost/mp11/set.hpp>
@@ -434,7 +440,7 @@ just a matter of applying it over the possible combinations of the variant values:

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

Why does this work? mp_product<F, @@ -442,6 +448,9 @@ where Ui traverse all possible combinations of list values. Since in our case all Li are std::variant, the result will also be std::variant. + (mp_product_q is the same + as mp_product, but for quoted + metafunctions such as our Qret<F>.)

One more step remains. Suppose that, as above, we're passing two variants @@ -1121,6 +1130,17 @@

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

+ As mp_product, but takes + a quoted metafunction. +

+
+
+
template<class L, std::size_t N> using mp_drop_c = /*...*/;
@@ -1222,6 +1242,53 @@
 
+
template<class L, std::size_t I, class... T> using mp_insert_c = mp_append<mp_take_c<L, I>, mp_push_front<mp_drop_c<L, I>, T...>>;
+
+

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

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

+ Same as mp_insert_c, but + with a type argument I. +

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

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

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

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

+
+
+
template<class L, class V, class W> using mp_replace = /*...*/;
@@ -1342,8 +1409,11 @@
 
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 + mp_find<L, V> returns the index at which the type + V is located in the list + L. It's an alias for mp_size_t<I>, + where I is the zero-based + index of the first occurence of V in L. If L does not contain V, mp_find<L, V> is mp_size<L>.

@@ -1453,6 +1523,21 @@ one element of L, mp_false otherwise. When L is empty, the result is mp_false.

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

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

+

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

+

@@ -1866,7 +1951,7 @@

- +

Last revised: May 12, 2017 at 16:48:16 GMT

Last revised: May 13, 2017 at 18:21:04 GMT


diff --git a/doc/mp11/algorithm.qbk b/doc/mp11/algorithm.qbk index b325077..8a555db 100644 --- a/doc/mp11/algorithm.qbk +++ b/doc/mp11/algorithm.qbk @@ -83,6 +83,12 @@ the Cartesian product of the lists, as if the elements `Ui` are formed by `n` ne It returns a list of type `L1` containing the results of the application of `F`. [endsect] +[section `mp_product_q`] + template using mp_product_q = mp_product; + +As `mp_product`, but takes a quoted metafunction. +[endsect] + [section `mp_drop_c`] template using mp_drop_c = /*...*/; @@ -133,6 +139,30 @@ Same as `mp_at_c`, but with a type argument `I`. `I::value` must be a nonnegativ Same as `mp_take_c`, but with a type argument `N`. `N::value` must be a nonnegative number. [endsect] +[section `mp_insert_c`] + template using mp_insert_c = mp_append, mp_push_front, T...>>; + +Inserts the elements `T...` into the list `L` at position `I` (a zero-based index). +[endsect] + +[section `mp_insert`] + template using mp_insert = mp_append, mp_push_front, T...>>; + +Same as `mp_insert_c`, but with a type argument `I`. +[endsect] + +[section `mp_erase_c`] + template using mp_erase = mp_append, mp_drop_c>; + +Removes from the list `L` the elements with indices from `I` (inclusive) to `J` (exclusive). +[endsect] + +[section `mp_erase`] + template using mp_erase = mp_append, mp_drop>; + +Same as `mp_erase_c`, but with a type arguments `I` and `J`. +[endsect] + [section `mp_replace`] template using mp_replace = /*...*/; @@ -191,8 +221,9 @@ for the elements of `L` and `mp_false` for the elements of `L`. Re [section `mp_find`] 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`. +`mp_find` returns the index at which the type `V` is located in the list `L`. It's an alias for `mp_size_t`, +where `I` is the zero-based index of the first occurence of `V` in `L`. If `L` does not contain `V`, `mp_find` +is `mp_size`. [endsect] [section `mp_find_if`] @@ -244,4 +275,12 @@ for the elements of `L` and `mp_false` for the elements of `L`. Re `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] +[section `mp_for_each(f)`] + template constexpr F mp_for_each(F&& f); + +`mp_for_each(f)` calls `f` with `mp_identity()` for each element `T` of the list `L`, in order. + +Returns `std::forward(f)`. +[endsect] + [endsect:algorithm] diff --git a/doc/mp11/examples.qbk b/doc/mp11/examples.qbk index 041c589..9e5a7de 100644 --- a/doc/mp11/examples.qbk +++ b/doc/mp11/examples.qbk @@ -115,10 +115,11 @@ We'll first define a helper quoted metafunction `Qret` that returns the resul 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 fn, std::remove_reference_t...>; + using R = mp_product_q, 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`. +possible combinations of list values. Since in our case all `Li` are `std::variant`, the result will also be `std::variant`. (`mp_product_q` is +the same as `mp_product`, but for quoted metafunctions such as our `Qret`.) One more step remains. Suppose that, as above, we're passing two variants of type `std::variant` and `F` is `[]( auto const& x, auto const& y ){ return x + y; }`. This will generate `R` of length 9, one per each combination, but many of those diff --git a/include/boost/mp11/algorithm.hpp b/include/boost/mp11/algorithm.hpp index ba7eedf..298c25a 100644 --- a/include/boost/mp11/algorithm.hpp +++ b/include/boost/mp11/algorithm.hpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace boost { @@ -208,6 +209,7 @@ template class F, class L1, class... L> struct mp_product_imp } // namespace detail template class F, class... L> using mp_product = typename detail::mp_product_impl::type; +template using mp_product_q = typename detail::mp_product_impl::type; // mp_drop(_c) namespace detail @@ -823,6 +825,44 @@ template struct mp_replace_at_impl template using mp_replace_at = typename detail::mp_replace_at_impl::type; template using mp_replace_at_c = typename detail::mp_replace_at_impl, W>::type; +//mp_for_each(f) +namespace detail +{ + +template BOOST_CONSTEXPR F mp_for_each_impl( mp_list, F && f ) +{ + using A = int[sizeof...(T)]; + return (void)A{ ((void)f(mp_identity()), 0)... }, std::forward(f); +} + +#if BOOST_WORKAROUND( BOOST_MSVC, <= 1800 ) + +template BOOST_CONSTEXPR F mp_for_each_impl( mp_list<>, F && f ) +{ + return std::forward(f); +} + +#endif + +} // namespace detail + +template BOOST_CONSTEXPR F mp_for_each( F && f ) +{ + return detail::mp_for_each_impl( mp_rename(), std::forward(f) ); +} + +// mp_insert +template using mp_insert = mp_append, mp_push_front, T...>>; + +// mp_insert_c +template using mp_insert_c = mp_append, mp_push_front, T...>>; + +// mp_erase +template using mp_erase = mp_append, mp_drop>; + +// mp_erase_c +template using mp_erase_c = mp_append, mp_drop_c>; + } // namespace mp11 } // namespace boost diff --git a/include/boost/tuple_for_each.hpp b/include/boost/tuple_for_each.hpp index 2d2d135..8e3d766 100644 --- a/include/boost/tuple_for_each.hpp +++ b/include/boost/tuple_for_each.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -20,6 +21,15 @@ template BOOST_CONSTEXPR F tuple_for_each_i return (void)A{ ((void)f(std::get(std::forward(tp))), 0)... }, std::forward(f); } +#if BOOST_WORKAROUND( BOOST_MSVC, <= 1800 ) + +template BOOST_CONSTEXPR F tuple_for_each_impl( Tp && tp, boost::integer_sequence, F && f ) +{ + return std::forward(f); +} + +#endif + } // namespace detail template BOOST_CONSTEXPR F tuple_for_each( Tp && tp, F && f ) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c627c6b..da5c569 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -64,6 +64,9 @@ run mp_any_of.cpp : : : $(REQ) ; run mp_none_of.cpp : : : $(REQ) ; run mp_replace_at.cpp : : : $(REQ) ; run mp_replace_at_c.cpp : : : $(REQ) ; +run mp_for_each.cpp : : : $(REQ) ; +run mp_insert.cpp : : : $(REQ) ; +run mp_erase.cpp : : : $(REQ) ; # integral run integral.cpp : : : $(REQ) ; diff --git a/test/mp_erase.cpp b/test/mp_erase.cpp new file mode 100644 index 0000000..10e9638 --- /dev/null +++ b/test/mp_erase.cpp @@ -0,0 +1,171 @@ + +// 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 +#include +#include +#include + +struct X1 {}; +struct X2 {}; +struct X3 {}; +struct X4 {}; +struct X5 {}; + +int main() +{ + using boost::mp11::mp_list; + using boost::mp11::mp_erase; + using boost::mp11::mp_erase_c; + using boost::mp11::mp_size_t; + + using _0 = mp_size_t<0>; + using _1 = mp_size_t<1>; + using _2 = mp_size_t<2>; + using _3 = mp_size_t<3>; + using _4 = mp_size_t<4>; + using _5 = mp_size_t<5>; + + { + using L1 = mp_list<>; + + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + + using L2 = mp_list; + + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + 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_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_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_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_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_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_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_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<>>)); + + using L3 = mp_list; + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<18>>, mp_list>)); + } + + { + using L1 = std::tuple<>; + + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + + using L2 = std::tuple; + + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + + 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, 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, 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, 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, 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, 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, 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, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple<>>)); + + using L3 = std::tuple; + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<18>>, std::tuple>)); + } + + return boost::report_errors(); +} diff --git a/test/mp_for_each.cpp b/test/mp_for_each.cpp new file mode 100644 index 0000000..31ad7c5 --- /dev/null +++ b/test/mp_for_each.cpp @@ -0,0 +1,73 @@ + +// 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 + + +#include +#include +#include +#include +#include +#include + +using boost::mp11::mp_identity; + +#if !defined( BOOST_NO_CXX14_CONSTEXPR ) +# define CONSTEXPR14 constexpr +#else +# define CONSTEXPR14 +#endif + +struct F +{ + int s; + + CONSTEXPR14 void operator()( mp_identity ) { s = s * 10 + 1; } + CONSTEXPR14 void operator()( mp_identity ) { s = s * 10 + 2; } + CONSTEXPR14 void operator()( mp_identity ) { s = s * 10 + 3; } +}; + +using boost::mp11::mp_list; +using boost::mp11::mp_for_each; + +int main() +{ + BOOST_TEST_EQ( (mp_for_each>( 11 )), 11 ); + BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 1 ); + BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 12 ); + BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 123 ); + + BOOST_TEST_EQ( (mp_for_each>( 11 )), 11 ); + BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 1 ); + BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 12 ); + BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 123 ); + + BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 12 ); + +#if defined( BOOST_NO_CXX11_CONSTEXPR ) || ( defined( _LIBCPP_VERSION ) && __cplusplus < 201400L ) +#else + + static_assert( mp_for_each>( 11 ) == 11, "mp_for_each>( 11 ) == 11" ); + static_assert( mp_for_each>( 12 ) == 12, "mp_for_each>( 12 ) == 12" ); + +#endif + +#if !defined( BOOST_NO_CXX14_CONSTEXPR ) && !BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) + + constexpr auto r1 = mp_for_each>( F{0} ); + static_assert( r1.s == 123, "r1.s == 123" ); + + constexpr auto r2 = mp_for_each>( F{0} ); + static_assert( r2.s == 123, "r2.s == 123" ); + + constexpr auto r3 = mp_for_each>( F{0} ); + static_assert( r3.s == 12, "r3.s == 12" ); + +#endif + + return boost::report_errors(); +} diff --git a/test/mp_insert.cpp b/test/mp_insert.cpp new file mode 100644 index 0000000..da5bc69 --- /dev/null +++ b/test/mp_insert.cpp @@ -0,0 +1,137 @@ + +// 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 +#include +#include +#include + +struct X1 {}; +struct X2 {}; +struct X3 {}; +struct X4 {}; +struct X5 {}; + +struct Y1 {}; +struct Y2 {}; + +int main() +{ + using boost::mp11::mp_list; + using boost::mp11::mp_insert; + using boost::mp11::mp_insert_c; + 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>, L1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1>, mp_list>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, mp_list>)); + + using L2 = mp_list; + + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + 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_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>, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L2>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, mp_list>)); + + using L3 = mp_list; + + BOOST_TEST_TRAIT_TRUE((std::is_same, L3>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L3>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, mp_list>)); + } + + { + using L1 = std::tuple<>; + + BOOST_TEST_TRAIT_TRUE((std::is_same, L1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1>, std::tuple>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, std::tuple>)); + + using L2 = std::tuple; + + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L2>)); + + 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, 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>, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L2>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, std::tuple>)); + + using L3 = std::tuple; + + BOOST_TEST_TRAIT_TRUE((std::is_same, L3>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, L3>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Y1, Y2>, std::tuple>)); + } + + return boost::report_errors(); +} diff --git a/test/mp_product.cpp b/test/mp_product.cpp index 696965b..25ef40f 100644 --- a/test/mp_product.cpp +++ b/test/mp_product.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -29,6 +30,8 @@ int main() { using boost::mp11::mp_list; using boost::mp11::mp_product; + using boost::mp11::mp_product_q; + using boost::mp11::mp_quote; { using L1 = std::tuple; @@ -36,6 +39,7 @@ int main() using L3 = std::pair; BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple, F, F, F, F, F>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1, L2, L3>, std::tuple, F, F, F, F, F>>)); } { @@ -44,6 +48,7 @@ int main() using L3 = std::pair; BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple<>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, L1, L2, L3>, std::tuple<>>)); } return boost::report_errors(); diff --git a/test/tuple_for_each.cpp b/test/tuple_for_each.cpp index 97de4a7..e8880dd 100644 --- a/test/tuple_for_each.cpp +++ b/test/tuple_for_each.cpp @@ -91,5 +91,19 @@ int main() } } + { + std::tuple<> tp; + + BOOST_TEST_EQ( boost::tuple_for_each( tp, 11 ), 11 ); + BOOST_TEST_EQ( boost::tuple_for_each( std::move( tp ), 12 ), 12 ); + } + + { + std::array tp; + + BOOST_TEST_EQ( boost::tuple_for_each( tp, 11 ), 11 ); + BOOST_TEST_EQ( boost::tuple_for_each( std::move( tp ), 12 ), 12 ); + } + return boost::report_errors(); } diff --git a/test/tuple_for_each_cx.cpp b/test/tuple_for_each_cx.cpp index c3accb4..305d737 100644 --- a/test/tuple_for_each_cx.cpp +++ b/test/tuple_for_each_cx.cpp @@ -31,9 +31,22 @@ struct assert_is_integral int main() { - constexpr std::tuple tp{ 1, 2, 3 }; - constexpr auto r = boost::tuple_for_each( tp, assert_is_integral() ); - (void)r; + { + constexpr std::tuple tp{ 1, 2, 3 }; + constexpr auto r = boost::tuple_for_each( tp, assert_is_integral() ); + (void)r; + } + +#if defined( __clang_major__ ) && __clang_major__ == 3 && __clang_minor__ < 9 +#else + + { + constexpr std::tuple<> tp; + constexpr auto r = boost::tuple_for_each( tp, 11 ); + static_assert( r == 11, "r == 11" ); + } + +#endif } #endif