From 8d9e6f50dd236c93172ec912a09b19fa880f43f3 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 15 Mar 2017 18:09:30 +0200 Subject: [PATCH 01/14] Add arguments to mp_quote, allowing partial application --- doc/html/mp11.html | 24 ++++++------ doc/mp11/utility.qbk | 11 +++--- include/boost/mp11/utility.hpp | 10 ++--- test/mp_quote.cpp | 68 +++++++++++++++++++++++++++++++--- 4 files changed, 87 insertions(+), 26 deletions(-) diff --git a/doc/html/mp11.html b/doc/html/mp11.html index cfd8531..0304c01 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -76,7 +76,7 @@ U...>
mp_valid<F, T...>
mp_defer<F, T...>
-
mp_quote<F>
+
mp_quote<F, T...>
mp_unquote<Q, T...>
Algorithms, <boost/mp11/algorithm.hpp>
@@ -490,18 +490,20 @@
-
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 apply = 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 apply + of the result is an alias for F; + otherwise, apply<U...> + is an alias for F<T..., U...>, + allowing partial application.

@@ -511,9 +513,9 @@
template<class Q, class... T> using mp_unquote = typename Q::template apply<T...>;
 

- mp_unquote<Q, T...>, where Q - is mp_quote<F>, + mp_unquote<Q, T...> evaluates the nested template apply of a quoted metafunction. mp_unquote<mp_quote<F>, T...> is an alias for F<T...>. + mp_unquote<mp_quote<F, T...>, U...> is an alias for F<T..., U...>.

@@ -914,7 +916,7 @@ - +

Last revised: March 14, 2017 at 20:19:38 GMT

Last revised: March 15, 2017 at 16:06:15 GMT


diff --git a/doc/mp11/utility.qbk b/doc/mp11/utility.qbk index 51c39d3..b0b4a4b 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 apply = 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 `apply` of the result is an alias for `F`; +otherwise, `apply` is an alias for `F`, allowing partial application. [endsect] [section `mp_unquote`] template using mp_unquote = typename Q::template apply; -`mp_unquote`, where `Q` is `mp_quote`, is an alias for `F`. +`mp_unquote` evaluates the nested template `apply` of a quoted metafunction. `mp_unquote, T...>` is an alias for `F`. `mp_unquote, U...>` is an alias for `F`. [endsect] [endsect] diff --git a/include/boost/mp11/utility.hpp b/include/boost/mp11/utility.hpp index a438a33..220155f 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. // @@ -102,9 +102,9 @@ 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 apply = F; }; // mp_unquote @@ -116,9 +116,9 @@ template struct mp_unquote_impl using type = typename Q::template apply; }; -template class F, class... T> struct mp_unquote_impl, T...> +template class F, class... T, class... U> struct mp_unquote_impl, U...> { - using type = F; + using type = F; }; } // namespace detail diff --git a/test/mp_quote.cpp b/test/mp_quote.cpp index 74a8193..39ab385 100644 --- a/test/mp_quote.cpp +++ b/test/mp_quote.cpp @@ -11,18 +11,76 @@ #include #include -struct X {}; +using boost::mp_unquote; + +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 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(); } From 9f35ce210757289b3598cb16ef1dce52a0e82c38 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 15 Mar 2017 19:43:06 +0200 Subject: [PATCH 02/14] Add some more documentation --- doc/html/mp11.html | 161 +++++++++++++++++++++++++++++++++++++++-- doc/mp11/algorithm.qbk | 61 +++++++++++++++- 2 files changed, 215 insertions(+), 7 deletions(-) diff --git a/doc/html/mp11.html b/doc/html/mp11.html index 0304c01..c8b05d3 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -94,8 +94,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>
@@ -529,6 +529,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. +

@@ -536,6 +543,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. +

@@ -543,6 +555,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>...>. +

@@ -550,6 +568,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. +

@@ -557,6 +581,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. +

@@ -564,6 +593,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. +

@@ -571,6 +605,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. +

@@ -578,6 +618,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. +

@@ -585,6 +631,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. +

@@ -592,6 +642,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. +

@@ -599,6 +655,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. +

@@ -606,6 +671,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. +

@@ -613,20 +683,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. +

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

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

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

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

@@ -634,6 +724,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. +

@@ -642,6 +736,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. +

@@ -649,6 +748,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. +

@@ -656,6 +760,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. +

@@ -663,6 +772,10 @@

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

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

@@ -670,6 +783,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. +

@@ -677,6 +795,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. +

@@ -684,6 +808,10 @@

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

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

@@ -691,6 +819,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. +

@@ -698,6 +832,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...>>. +

@@ -705,6 +852,10 @@

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

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

@@ -916,7 +1067,7 @@

- +

Last revised: March 15, 2017 at 16:06:15 GMT

Last revised: March 15, 2017 at 17:28:31 GMT


diff --git a/doc/mp11/algorithm.qbk b/doc/mp11/algorithm.qbk index ed9edcd..7025c19 100644 --- a/doc/mp11/algorithm.qbk +++ b/doc/mp11/algorithm.qbk @@ -10,106 +10,163 @@ [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 = /*...*/; + +`mp_sort` sorts the list `L` according to the strict weak ordering `mp_to_bool>`. [endsect] [section `mp_find_index`] From adaa60dbc2b0d6e3942a6909a442dc92bb69f506 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 15 Mar 2017 20:03:56 +0200 Subject: [PATCH 03/14] Rename mp_find_index to mp_find --- include/boost/mp11/algorithm.hpp | 48 +++++++++++------------- test/Jamfile.v2 | 2 - test/mp_find.cpp | 29 ++++++++++----- test/mp_find_if.cpp | 25 +++++++++---- test/mp_find_index.cpp | 63 -------------------------------- test/mp_find_index_if.cpp | 59 ------------------------------ 6 files changed, 57 insertions(+), 169 deletions(-) delete mode 100644 test/mp_find_index.cpp delete mode 100644 test/mp_find_index_if.cpp diff --git a/include/boost/mp11/algorithm.hpp b/include/boost/mp11/algorithm.hpp index a25f48f..4cad722 100644 --- a/include/boost/mp11/algorithm.hpp +++ b/include/boost/mp11/algorithm.hpp @@ -490,15 +490,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 +508,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 +518,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 +526,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 +548,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 +573,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 +581,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 diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index b00e64c..2cd6766 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) ; diff --git a/test/mp_find.cpp b/test/mp_find.cpp index b9b3b2e..c9ee794 100644 --- a/test/mp_find.cpp +++ b/test/mp_find.cpp @@ -23,31 +23,40 @@ int main() { using boost::mp_list; using boost::mp_find; + using boost::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..2500381 100644 --- a/test/mp_find_if.cpp +++ b/test/mp_find_if.cpp @@ -21,29 +21,38 @@ int main() { using boost::mp_list; using boost::mp_find_if; + using boost::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(); -} From ac42a4b3c65cb8dc5c5d87e8010f6554f32f023e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 15 Mar 2017 20:19:36 +0200 Subject: [PATCH 04/14] Add more documentation. --- doc/html/mp11.html | 77 +++++++++++++++++++++++++++++++----------- doc/mp11/algorithm.qbk | 32 ++++++++++++------ 2 files changed, 80 insertions(+), 29 deletions(-) diff --git a/doc/html/mp11.html b/doc/html/mp11.html index c8b05d3..6489b42 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -108,8 +108,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>
@@ -859,31 +857,31 @@
-
template<class L, class V> using mp_find_index = /*...*/;
-
-
-
- -
template<class L, template<class...> class P> using mp_find_index_if = /*...*/;
-
-
-
- -
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>. +

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

@@ -891,6 +889,9 @@

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

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

@@ -898,6 +899,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. +

@@ -905,6 +915,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. +

@@ -912,6 +927,11 @@

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

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

@@ -919,6 +939,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. +

@@ -926,6 +953,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. +

@@ -933,6 +967,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. +

@@ -1067,7 +1106,7 @@
- +

Last revised: March 15, 2017 at 17:28:31 GMT

Last revised: March 15, 2017 at 18:15:15 GMT


diff --git a/doc/mp11/algorithm.qbk b/doc/mp11/algorithm.qbk index 7025c19..ad25649 100644 --- a/doc/mp11/algorithm.qbk +++ b/doc/mp11/algorithm.qbk @@ -169,48 +169,60 @@ for the elements of `L` and `mp_false` for the elements of `L`. Re `mp_sort` sorts the list `L` according to the strict weak ordering `mp_to_bool>`. [endsect] -[section `mp_find_index`] - template using mp_find_index = /*...*/; -[endsect] - -[section `mp_find_index_if`] - template class P> using mp_find_index_if = /*...*/; -[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] From a231733c7e3e27b38f7d1bf66fb822a68c4b88d5 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 15 Mar 2017 21:23:15 +0200 Subject: [PATCH 05/14] Move everything to namespace mp11 --- include/boost/mp11/algorithm.hpp | 3 +++ include/boost/mp11/detail/mp_count.hpp | 3 +++ include/boost/mp11/detail/mp_list.hpp | 3 +++ include/boost/mp11/detail/mp_map_find.hpp | 3 +++ include/boost/mp11/detail/mp_plus.hpp | 3 +++ include/boost/mp11/function.hpp | 3 +++ include/boost/mp11/integral.hpp | 3 +++ include/boost/mp11/list.hpp | 3 +++ include/boost/mp11/map.hpp | 3 +++ include/boost/mp11/set.hpp | 3 +++ include/boost/mp11/utility.hpp | 3 +++ test/integral.cpp | 14 +++++++------- test/mp_all.cpp | 10 +++++----- test/mp_all_of.cpp | 8 ++++---- test/mp_and.cpp | 10 +++++----- test/mp_any.cpp | 10 +++++----- test/mp_any_of.cpp | 8 ++++---- test/mp_append.cpp | 4 ++-- test/mp_assign.cpp | 4 ++-- test/mp_at.cpp | 8 ++++---- test/mp_clear.cpp | 4 ++-- test/mp_contains.cpp | 8 ++++---- test/mp_copy_if.cpp | 4 ++-- test/mp_count.cpp | 6 +++--- test/mp_count_if.cpp | 6 +++--- test/mp_defer.cpp | 10 +++++++--- test/mp_drop.cpp | 8 ++++---- test/mp_empty.cpp | 8 ++++---- test/mp_eval_if.cpp | 10 +++++----- test/mp_fill.cpp | 4 ++-- test/mp_find.cpp | 6 +++--- test/mp_find_if.cpp | 6 +++--- test/mp_fold.cpp | 8 ++++---- test/mp_front.cpp | 6 +++--- test/mp_identity.cpp | 4 ++-- test/mp_if.cpp | 8 ++++---- test/mp_inherit.cpp | 2 +- test/mp_iota.cpp | 10 +++++----- test/mp_map_contains.cpp | 8 ++++---- test/mp_map_erase.cpp | 4 ++-- test/mp_map_find.cpp | 4 ++-- test/mp_map_insert.cpp | 6 +++--- test/mp_map_replace.cpp | 6 +++--- test/mp_map_update.cpp | 6 +++--- test/mp_none_of.cpp | 8 ++++---- test/mp_or.cpp | 10 +++++----- test/mp_partition.cpp | 4 ++-- test/mp_pop_front.cpp | 6 +++--- test/mp_product.cpp | 4 ++-- test/mp_push_back.cpp | 4 ++-- test/mp_push_front.cpp | 4 ++-- test/mp_quote.cpp | 6 +++--- test/mp_remove.cpp | 4 ++-- test/mp_remove_if.cpp | 4 ++-- test/mp_rename.cpp | 4 ++-- test/mp_repeat.cpp | 14 +++++++------- test/mp_replace.cpp | 4 ++-- test/mp_replace_if.cpp | 4 ++-- test/mp_reverse.cpp | 4 ++-- test/mp_reverse_fold.cpp | 11 +++++++---- test/mp_second.cpp | 4 ++-- test/mp_set_contains.cpp | 8 ++++---- test/mp_set_push_back.cpp | 4 ++-- test/mp_set_push_front.cpp | 4 ++-- test/mp_size.cpp | 6 +++--- test/mp_sort.cpp | 6 +++--- test/mp_take.cpp | 8 ++++---- test/mp_third.cpp | 4 ++-- test/mp_transform.cpp | 4 ++-- test/mp_transform_if.cpp | 8 +++++--- test/mp_unique.cpp | 4 ++-- test/mp_valid.cpp | 4 ++-- 72 files changed, 231 insertions(+), 189 deletions(-) diff --git a/include/boost/mp11/algorithm.hpp b/include/boost/mp11/algorithm.hpp index 4cad722..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 @@ -751,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..0fd4f6e 100644 --- a/include/boost/mp11/function.hpp +++ b/include/boost/mp11/function.hpp @@ -15,6 +15,8 @@ namespace boost { +namespace mp11 +{ // mp_equal_to template using mp_equal_to = mp_bool< T1::value == T2::value >; @@ -75,6 +77,7 @@ template struct mp_or_impl } // 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 220155f..8ac684c 100644 --- a/include/boost/mp11/utility.hpp +++ b/include/boost/mp11/utility.hpp @@ -12,6 +12,8 @@ namespace boost { +namespace mp11 +{ // mp_identity template struct mp_identity @@ -125,6 +127,7 @@ template class F, class... T, class... U> struct mp_unquote_i template using mp_unquote = typename detail::mp_unquote_impl::type; +} // namespace mp11 } // namespace boost #endif // #ifndef BOOST_MP11_UTILITY_HPP_INCLUDED 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..6c06ded 100644 --- a/test/mp_and.cpp +++ b/test/mp_and.cpp @@ -14,11 +14,11 @@ 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>)); 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 c9ee794..21aeb26 100644 --- a/test/mp_find.cpp +++ b/test/mp_find.cpp @@ -21,9 +21,9 @@ struct X3 {}; int main() { - using boost::mp_list; - using boost::mp_find; - using boost::mp_size_t; + using boost::mp11::mp_list; + using boost::mp11::mp_find; + using boost::mp11::mp_size_t; { using L1 = mp_list<>; diff --git a/test/mp_find_if.cpp b/test/mp_find_if.cpp index 2500381..6310390 100644 --- a/test/mp_find_if.cpp +++ b/test/mp_find_if.cpp @@ -19,9 +19,9 @@ struct X1 {}; int main() { - using boost::mp_list; - using boost::mp_find_if; - using boost::mp_size_t; + using boost::mp11::mp_list; + using boost::mp11::mp_find_if; + using boost::mp11::mp_size_t; { using L1 = mp_list<>; 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_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..e468be5 100644 --- a/test/mp_or.cpp +++ b/test/mp_or.cpp @@ -14,11 +14,11 @@ 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>)); 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 39ab385..26a84af 100644 --- a/test/mp_quote.cpp +++ b/test/mp_quote.cpp @@ -11,7 +11,7 @@ #include #include -using boost::mp_unquote; +using boost::mp11::mp_unquote; template struct X {}; @@ -28,8 +28,8 @@ 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::mp11::mp_identity_t; + using boost::mp11::mp_quote; { using Q = mp_quote; 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)); From 7bbdaacda1727d2d1ff30a605a08630ce477f03d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 16 Mar 2017 17:35:47 +0200 Subject: [PATCH 06/14] Remove mp_equal_to. --- include/boost/mp11/function.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/include/boost/mp11/function.hpp b/include/boost/mp11/function.hpp index 0fd4f6e..752537b 100644 --- a/include/boost/mp11/function.hpp +++ b/include/boost/mp11/function.hpp @@ -18,9 +18,6 @@ namespace boost namespace mp11 { -// mp_equal_to -template using mp_equal_to = mp_bool< T1::value == T2::value >; - // mp_all template using mp_all = mp_bool< mp_count_if< mp_list, mp_to_bool >::value == sizeof...(T) >; From e4f74886525418581f265ea3f8fa6f2340661aee Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 16 Mar 2017 17:49:57 +0200 Subject: [PATCH 07/14] Change mp_and and mp_or to match std::conjuction and std::disjunction --- include/boost/mp11/function.hpp | 16 +++++++++--- test/mp_and.cpp | 30 +++++++++++----------- test/mp_or.cpp | 44 ++++++++++++++++----------------- 3 files changed, 50 insertions(+), 40 deletions(-) diff --git a/include/boost/mp11/function.hpp b/include/boost/mp11/function.hpp index 752537b..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. // @@ -39,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 @@ -67,9 +72,14 @@ 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 diff --git a/test/mp_and.cpp b/test/mp_and.cpp index 6c06ded..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. // @@ -25,23 +25,23 @@ 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>, 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_or.cpp b/test/mp_or.cpp index e468be5..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. // @@ -25,23 +25,23 @@ 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>, 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(); From 445d033ddc5fa3146a4bd53c1a96d09643891de3 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 16 Mar 2017 19:45:47 +0200 Subject: [PATCH 08/14] More documentation. --- doc/html/mp11.html | 228 +++++++++++++++++++++++++++++++++- doc/mp11.qbk | 7 +- doc/mp11/function.qbk | 40 ++++++ doc/mp11/integer_sequence.qbk | 45 +++++++ doc/mp11/integral.qbk | 2 + doc/mp11/overview.qbk | 29 +++++ doc/mp11/tuple_for_each.qbk | 22 ++++ 7 files changed, 370 insertions(+), 3 deletions(-) create mode 100644 doc/mp11/function.qbk create mode 100644 doc/mp11/integer_sequence.qbk create mode 100644 doc/mp11/overview.qbk create mode 100644 doc/mp11/tuple_for_each.qbk diff --git a/doc/html/mp11.html b/doc/html/mp11.html index 6489b42..1945ad0 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -134,6 +134,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
@@ -142,17 +161,54 @@ 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::tuple<int, float>, std::add_pointer_t> gives us std::tuple<int*, float*>, but we can also apply mp_list + to the same tuple: +

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

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

+

+ 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> @@ -1103,10 +1159,178 @@

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

+
+
+
+ +

+ The contents of this header are defined in namespace boost. +

+
+ +
template<class T, T... I> struct integer_sequence
+{
+};
+
+

+ integer_sequence<T, I...> holds a sequence of integers of + type T. Same as C++14's + std::integer_sequence. +

+
+
+ +
template<class T, T N> using make_integer_sequence = /*...*/;
+
+

+ make_integer_sequence<T, N> is integer_sequence<T, 0, + 1, ..., N-1>. + Same as C++14's std::make_integer_sequence. +

+
+
+ +
template<std::size_t... I> using index_sequence = integer_sequence<std::size_t, I...>;
+
+

+ index_sequence<I...> + is an alias for integer_sequence<size_t, I...>. + Same as C++14's std::index_sequence. +

+
+
+ +
template<std::size_t N> using make_index_sequence = make_integer_sequence<std::size_t, N>;
+
+

+ make_index_sequence<N> + is index_sequence<0, 1, ..., N-1>. Same as C++14's std::make_index_sequence. +

+
+
+ +
template<class... T> using index_sequence_for = make_integer_sequence<std::size_t, sizeof...(T)>;
+
+

+ index_sequence_for<N> + is make_index_sequence<sizeof...(T)>. Same as C++14's std::index_sequence_for. +

+
+
+
+ +

+ The contents of this header are defined in namespace boost. +

+
+ +
template<class Tp, class F> constexpr F tuple_for_each(Tp&& tp, F&& f);
+
+

+ tuple_for_each(tp, f) applies + the function object f to + each element of tp by evaluating + the expression f(std::get<J>(std::forward<Tp>(tp))) + for J in 0..N-1, + where N is std::tuple_size<std::remove_reference_t<Tp>>::value. +

+

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

+
+
- +

Last revised: March 15, 2017 at 18:15:15 GMT

Last revised: March 16, 2017 at 17:05:33 GMT


diff --git a/doc/mp11.qbk b/doc/mp11.qbk index 4b9795f..b28efa0 100644 --- a/doc/mp11.qbk +++ b/doc/mp11.qbk @@ -25,17 +25,22 @@ [section Overview] -... +[include mp11/overview.qbk] [endsect] [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/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..89f7cff --- /dev/null +++ b/doc/mp11/overview.qbk @@ -0,0 +1,29 @@ +[/ + / 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) + /] + +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, std::add_pointer_t>` +gives us `std::tuple`, but we can also apply `mp_list` to the same tuple: + + using R = mp_transform, mp_list>; + +and get `std::tuple, mp_list>`. 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] From b4ae7ab091d21e31a30019f5b7816c92dd81035a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 16 Mar 2017 19:59:20 +0200 Subject: [PATCH 09/14] Update README. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c7f7fd..84b28db 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ # mp11 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`. From 401ddcb1c1a25fa006adeb8b065b822db467be84 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 16 Mar 2017 20:02:06 +0200 Subject: [PATCH 10/14] Update README. --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 84b28db..e36143f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -# 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). From 946937b5ab475722538f1ccafd666b55fda0f27a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 16 Mar 2017 21:14:42 +0200 Subject: [PATCH 11/14] Rename Q::apply to Q::invoke, mp_unquote to mp_invoke. --- doc/mp11/utility.qbk | 10 +++--- include/boost/mp11/utility.hpp | 10 +++--- test/Jamfile.v2 | 1 + test/mp_invoke.cpp | 56 ++++++++++++++++++++++++++++++++++ test/mp_quote.cpp | 20 ++++++------ 5 files changed, 77 insertions(+), 20 deletions(-) create mode 100644 test/mp_invoke.cpp diff --git a/doc/mp11/utility.qbk b/doc/mp11/utility.qbk index b0b4a4b..6f12df0 100644 --- a/doc/mp11/utility.qbk +++ b/doc/mp11/utility.qbk @@ -64,17 +64,17 @@ When `mp_valid` is `mp_true`, `mp_defer` is a struct with a ne [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. In the common case `mp_quote`, the nested template `apply` of the result is an alias for `F`; -otherwise, `apply` is an alias for `F`, allowing partial application. +`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; + template using mp_unquote = typename Q::template invoke; -`mp_unquote` evaluates the nested template `apply` of a quoted metafunction. `mp_unquote, T...>` is an alias for `F`. `mp_unquote, U...>` is an alias for `F`. +`mp_unquote` evaluates the nested template `invoke` of a quoted metafunction. `mp_unquote, T...>` is an alias for `F`. `mp_unquote, U...>` is an alias for `F`. [endsect] [endsect] diff --git a/include/boost/mp11/utility.hpp b/include/boost/mp11/utility.hpp index 8ac684c..0f34d3f 100644 --- a/include/boost/mp11/utility.hpp +++ b/include/boost/mp11/utility.hpp @@ -106,26 +106,26 @@ template class F, class... T> using mp_defer = mp_if 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, class... U> struct mp_unquote_impl, U...> +template class F, class... T, class... U> struct mp_invoke_impl, U...> { 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 diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 2cd6766..29c916b 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -69,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/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_quote.cpp b/test/mp_quote.cpp index 26a84af..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,13 +11,13 @@ #include #include -using boost::mp11::mp_unquote; +using boost::mp11::mp_invoke; template struct X {}; template class F, class... T> using Y = X...>; -template using Z = X...>; +template using Z = X...>; struct B {}; struct D1: B {}; @@ -34,27 +34,27 @@ int main() { 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>)); + 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>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, X>)); } { using Q = mp_quote; - // using R1 = Y; + // using R1 = Y; // BOOST_TEST_TRAIT_TRUE((std::is_same>)); // // error: pack expansion used as argument for non-pack parameter of alias template @@ -71,7 +71,7 @@ int main() #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 ) #else - using R1 = Y; + using R1 = Y; BOOST_TEST_TRAIT_TRUE((std::is_same>)); #endif From c0fd3871eba95ffceffd0f05047f98df6c9a2ddf Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 17 Mar 2017 01:39:52 +0200 Subject: [PATCH 12/14] Update documentation. --- doc/html/mp11.html | 18 +++++++++--------- doc/mp11/utility.qbk | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/html/mp11.html b/doc/html/mp11.html index 1945ad0..52ca3fb 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -77,7 +77,7 @@
mp_valid<F, T...>
mp_defer<F, T...>
mp_quote<F, T...>
-
mp_unquote<Q, T...>
+
mp_invoke<Q, T...>
Algorithms, <boost/mp11/algorithm.hpp>
@@ -548,28 +548,28 @@
template<template<class...> class F, class... T> struct mp_quote
 {
-    template<class... U> using apply = F<T..., U...>;
+    template<class... U> using invoke = F<T..., U...>;
 };
 

mp_quote<F, T...> transforms the template F into a type. In the common case mp_quote<F>, - the nested template apply + the nested template invoke of the result is an alias for F; - otherwise, apply<U...> + 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...> evaluates the nested template apply of a quoted metafunction. mp_unquote<mp_quote<F>, T...> + 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_unquote<mp_quote<F, T...>, U...> is an alias for F<T..., U...>. + mp_invoke<mp_quote<F, T...>, U...> is an alias for F<T..., U...>.

@@ -1330,7 +1330,7 @@ - +

Last revised: March 16, 2017 at 17:05:33 GMT

Last revised: March 16, 2017 at 23:37:05 GMT


diff --git a/doc/mp11/utility.qbk b/doc/mp11/utility.qbk index 6f12df0..79c7c20 100644 --- a/doc/mp11/utility.qbk +++ b/doc/mp11/utility.qbk @@ -71,10 +71,10 @@ When `mp_valid` is `mp_true`, `mp_defer` is a struct with a ne otherwise, `invoke` is an alias for `F`, allowing partial application. [endsect] -[section `mp_unquote`] - template using mp_unquote = typename Q::template invoke; +[section `mp_invoke`] + template using mp_invoke = typename Q::template invoke; -`mp_unquote` evaluates the nested template `invoke` of a quoted metafunction. `mp_unquote, T...>` is an alias for `F`. `mp_unquote, U...>` 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] From 98c9595bf4dafb6e73010be8b248164a847cd4aa Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 17 Mar 2017 02:28:03 +0200 Subject: [PATCH 13/14] Add Definitions section. --- doc/html/mp11.html | 45 +++++++++++++++++++++++++++++++++++++++- doc/mp11.qbk | 1 + doc/mp11/definitions.qbk | 32 ++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 doc/mp11/definitions.qbk diff --git a/doc/html/mp11.html b/doc/html/mp11.html index 52ca3fb..a1235fd 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -35,6 +35,7 @@
Overview
Reference
+
Definitions
Integral Constants, <boost/mp11/integral.hpp>
mp_bool<B>
@@ -202,6 +203,48 @@

+

+ 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; };
+
+
+ - +

Last revised: March 16, 2017 at 23:37:05 GMT

Last revised: March 17, 2017 at 00:17:37 GMT


diff --git a/doc/mp11.qbk b/doc/mp11.qbk index b28efa0..6a3052e 100644 --- a/doc/mp11.qbk +++ b/doc/mp11.qbk @@ -33,6 +33,7 @@ The contents of the library are in namespace `boost::mp11`, unless specified otherwise. +[include mp11/definitions.qbk] [include mp11/integral.qbk] [include mp11/list.qbk] [include mp11/utility.qbk] 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] From 077d46820fc1df948af3fbe2b57af3818f84248f Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 17 Mar 2017 05:55:27 +0200 Subject: [PATCH 14/14] Add examples to documentation. --- doc/html/mp11.html | 325 ++++++++++++++++++++++++++++++++++++------ doc/mp11.qbk | 7 +- doc/mp11/examples.qbk | 175 +++++++++++++++++++++++ doc/mp11/overview.qbk | 10 +- 4 files changed, 462 insertions(+), 55 deletions(-) create mode 100644 doc/mp11/examples.qbk diff --git a/doc/html/mp11.html b/doc/html/mp11.html index a1235fd..8994454 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -33,9 +33,16 @@

Table of Contents

Overview
+
Definitions
+
Examples
+
+
Generating Test + Cases
+
Computing Return + Types
+
Reference
-
Definitions
Integral Constants, <boost/mp11/integral.hpp>
mp_bool<B>
@@ -175,7 +182,7 @@ 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, + 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. @@ -184,10 +191,11 @@ 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::tuple<int, float>, std::add_pointer_t> gives us std::tuple<int*, float*>, but we can also apply mp_list + 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<std::tuple<int, float>, mp_list>;
+
using R = mp_transform<mp_list, std::tuple<int, float>>;
 

and get std::tuple<mp_list<int>, mp_list<float>>. @@ -195,6 +203,271 @@

+

+ 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; };
+
+
+
+ +
+ +

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

@@ -203,48 +476,6 @@

-

- 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; };
-
-
-
- +

Last revised: March 17, 2017 at 00:17:37 GMT

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


diff --git a/doc/mp11.qbk b/doc/mp11.qbk index 6a3052e..f1f55e9 100644 --- a/doc/mp11.qbk +++ b/doc/mp11.qbk @@ -23,17 +23,14 @@ [template endsimplesect[] [block '''''']] -[section Overview] - [include mp11/overview.qbk] - -[endsect] +[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/definitions.qbk] [include mp11/integral.qbk] [include mp11/list.qbk] [include mp11/utility.qbk] 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/overview.qbk b/doc/mp11/overview.qbk index 89f7cff..9c1389d 100644 --- a/doc/mp11/overview.qbk +++ b/doc/mp11/overview.qbk @@ -6,6 +6,8 @@ / 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] @@ -15,15 +17,17 @@ The general principles upon which Mp11 is built are that algorithms and metafunc 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, +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, 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, mp_list>; + using R = mp_transform>; and get `std::tuple, mp_list>`. + +[endsect]