From d97b21261f584ddf3f65c505a706b296e550c90d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 12 May 2017 23:37:37 +0300 Subject: [PATCH 01/10] Add tests for tuple_for_each and empty tuples --- include/boost/tuple_for_each.hpp | 10 ++++++++++ test/tuple_for_each.cpp | 14 ++++++++++++++ test/tuple_for_each_cx.cpp | 14 +++++++++++--- 3 files changed, 35 insertions(+), 3 deletions(-) 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/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..85189d0 100644 --- a/test/tuple_for_each_cx.cpp +++ b/test/tuple_for_each_cx.cpp @@ -31,9 +31,17 @@ 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; + } + + { + constexpr std::tuple<> tp; + constexpr auto r = boost::tuple_for_each( tp, 11 ); + static_assert( r == 11, "r == 11" ); + } } #endif From 893d84fda2b92ffcc07d05671b019bd8acb4fff0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 13 May 2017 00:10:50 +0300 Subject: [PATCH 02/10] Add mp_for_each --- include/boost/mp11/algorithm.hpp | 26 ++++++++++++ test/Jamfile.v2 | 1 + test/mp_for_each.cpp | 72 ++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 test/mp_for_each.cpp diff --git a/include/boost/mp11/algorithm.hpp b/include/boost/mp11/algorithm.hpp index ba7eedf..44439dd 100644 --- a/include/boost/mp11/algorithm.hpp +++ b/include/boost/mp11/algorithm.hpp @@ -20,6 +20,7 @@ #include #include #include +#include namespace boost { @@ -823,6 +824,31 @@ 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; +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) ); +} + } // namespace mp11 } // namespace boost diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c627c6b..f7afbe4 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -64,6 +64,7 @@ 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) ; # integral run integral.cpp : : : $(REQ) ; diff --git a/test/mp_for_each.cpp b/test/mp_for_each.cpp new file mode 100644 index 0000000..b7d0a21 --- /dev/null +++ b/test/mp_for_each.cpp @@ -0,0 +1,72 @@ + +// 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 ) + + 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(); +} From 88dceba219df101ee213ad50f99b79839d3b9d47 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 13 May 2017 00:14:26 +0300 Subject: [PATCH 03/10] constexpr tuple<> tp doesn't work on clang < 3.9 --- test/tuple_for_each_cx.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/tuple_for_each_cx.cpp b/test/tuple_for_each_cx.cpp index 85189d0..305d737 100644 --- a/test/tuple_for_each_cx.cpp +++ b/test/tuple_for_each_cx.cpp @@ -37,11 +37,16 @@ int main() (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 From 0241f0531b85aeda11f030c83a7ec5b34de8a71b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 13 May 2017 00:23:58 +0300 Subject: [PATCH 04/10] Update documentation --- doc/html/mp11.html | 18 +++++++++++++++++- doc/mp11/algorithm.qbk | 8 ++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/doc/html/mp11.html b/doc/html/mp11.html index cd95a45..5f9f706 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -136,6 +136,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>
@@ -1453,6 +1454,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 +1882,7 @@

- +

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

Last revised: May 12, 2017 at 21:20:08 GMT


diff --git a/doc/mp11/algorithm.qbk b/doc/mp11/algorithm.qbk index b325077..adea9a1 100644 --- a/doc/mp11/algorithm.qbk +++ b/doc/mp11/algorithm.qbk @@ -244,4 +244,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] From 4338af3c49e10a798ef5b2ef306395b3f183418f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 13 May 2017 01:41:09 +0300 Subject: [PATCH 05/10] Disable constexpr mp_for_each test on libc++/C++11 due to std::forward not constexpr --- test/mp_for_each.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/mp_for_each.cpp b/test/mp_for_each.cpp index b7d0a21..31ad7c5 100644 --- a/test/mp_for_each.cpp +++ b/test/mp_for_each.cpp @@ -48,7 +48,8 @@ int main() BOOST_TEST_EQ( (mp_for_each>( F{0} ).s), 12 ); -#if !defined( BOOST_NO_CXX11_CONSTEXPR ) +#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" ); From de8b2ef76b73548eb731ca3bbacae6666f434698 Mon Sep 17 00:00:00 2001 From: Bjorn Reese Date: Sat, 13 May 2017 11:43:31 +0200 Subject: [PATCH 06/10] Added synopsis for mp_find --- doc/mp11/algorithm.qbk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/mp11/algorithm.qbk b/doc/mp11/algorithm.qbk index adea9a1..2a5e578 100644 --- a/doc/mp11/algorithm.qbk +++ b/doc/mp11/algorithm.qbk @@ -191,6 +191,8 @@ for the elements of `L` and `mp_false` for the elements of `L`. Re [section `mp_find`] template using mp_find = /*...*/; +Returns the index at which type `V` is located in list `L`. + `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] From f840fdac5e66a5e0ba6599e191b2212d193f305b Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 13 May 2017 20:56:52 +0300 Subject: [PATCH 07/10] Reword slightly --- doc/mp11/algorithm.qbk | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/mp11/algorithm.qbk b/doc/mp11/algorithm.qbk index 2a5e578..b67cfa3 100644 --- a/doc/mp11/algorithm.qbk +++ b/doc/mp11/algorithm.qbk @@ -191,10 +191,9 @@ for the elements of `L` and `mp_false` for the elements of `L`. Re [section `mp_find`] template using mp_find = /*...*/; -Returns the index at which type `V` is located in list `L`. - -`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`] From 647f66935323d5efcb5682612d258edf40552267 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 13 May 2017 21:07:54 +0300 Subject: [PATCH 08/10] Add mp_product_q, update documentation --- doc/html/mp11.html | 21 ++++++++++++++++++--- doc/mp11/algorithm.qbk | 6 ++++++ include/boost/mp11/algorithm.hpp | 1 + test/mp_product.cpp | 5 +++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/doc/html/mp11.html b/doc/html/mp11.html index 5f9f706..f5a0537 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>
@@ -1122,6 +1123,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 = /*...*/;
@@ -1343,8 +1355,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>.

@@ -1882,7 +1897,7 @@
- +

Last revised: May 12, 2017 at 21:20:08 GMT

Last revised: May 13, 2017 at 18:01:55 GMT


diff --git a/doc/mp11/algorithm.qbk b/doc/mp11/algorithm.qbk index b67cfa3..fe9cb95 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 = /*...*/; diff --git a/include/boost/mp11/algorithm.hpp b/include/boost/mp11/algorithm.hpp index 44439dd..6511c81 100644 --- a/include/boost/mp11/algorithm.hpp +++ b/include/boost/mp11/algorithm.hpp @@ -209,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 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(); From ac28cf9b3ff5d6b43ea10859cc6f3318178fb593 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 13 May 2017 21:11:23 +0300 Subject: [PATCH 09/10] Use mp_product_q in example --- doc/html/mp11.html | 7 +++++-- doc/mp11/examples.qbk | 5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/doc/html/mp11.html b/doc/html/mp11.html index f5a0537..10403a9 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -436,7 +436,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, @@ -444,6 +444,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 @@ -1897,7 +1900,7 @@ - +

Last revised: May 13, 2017 at 18:01:55 GMT

Last revised: May 13, 2017 at 18:11:09 GMT


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 From 15e45290d0071736de8f07c956c931d927c8d58e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 13 May 2017 21:52:56 +0300 Subject: [PATCH 10/10] Add mp_insert, mp_erase --- doc/html/mp11.html | 53 +++++++++- doc/mp11/algorithm.qbk | 24 +++++ include/boost/mp11/algorithm.hpp | 13 +++ test/Jamfile.v2 | 2 + test/mp_erase.cpp | 171 +++++++++++++++++++++++++++++++ test/mp_insert.cpp | 137 +++++++++++++++++++++++++ 6 files changed, 399 insertions(+), 1 deletion(-) create mode 100644 test/mp_erase.cpp create mode 100644 test/mp_insert.cpp diff --git a/doc/html/mp11.html b/doc/html/mp11.html index 10403a9..b5bbe7b 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -119,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>
@@ -1238,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 = /*...*/;
@@ -1900,7 +1951,7 @@
 
- +

Last revised: May 13, 2017 at 18:11:09 GMT

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


diff --git a/doc/mp11/algorithm.qbk b/doc/mp11/algorithm.qbk index fe9cb95..8a555db 100644 --- a/doc/mp11/algorithm.qbk +++ b/doc/mp11/algorithm.qbk @@ -139,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 = /*...*/; diff --git a/include/boost/mp11/algorithm.hpp b/include/boost/mp11/algorithm.hpp index 6511c81..298c25a 100644 --- a/include/boost/mp11/algorithm.hpp +++ b/include/boost/mp11/algorithm.hpp @@ -825,6 +825,7 @@ 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 { @@ -850,6 +851,18 @@ 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/test/Jamfile.v2 b/test/Jamfile.v2 index f7afbe4..da5c569 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -65,6 +65,8 @@ 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_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(); +}