diff --git a/doc/html/mp11.html b/doc/html/mp11.html index f419f7b..a6e817b 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -233,11 +233,11 @@

A quoted metafunction is a class with a public metafunction - called invoke, for example + called fn, 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)>; };
+
struct Q1 { template<class...> using fn = void; };
+struct Q2 { template<class T> using fn = T*; };
+struct Q3 { template<class... T> using fn = std::integral_constant<std::size_t, sizeof...(T)>; };
 

An integral constant type is a class with a public member @@ -391,7 +391,7 @@

template<class F> struct Qret
 {
-    template<class... T> using invoke = decltype( std::declval<F>()( std::declval<T>()... ) );
+    template<class... T> using fn = decltype( std::declval<F>()( std::declval<T>()... ) );
 };
 

@@ -403,7 +403,7 @@ 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>...>;
+
using R = mp_product<Qret<F>::template fn, std::remove_reference_t<V>...>;
 

Why does this work? mp_product<F, @@ -422,7 +422,7 @@ 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>...>>;
+
using R = mp_unique<mp_product<Qret<F>::template fn, std::remove_reference_t<V>...>>;
 

and we're done: @@ -438,12 +438,12 @@ template<class F> struct Qret { - template<class... T> using invoke = decltype( std::declval<F>()( std::declval<T>()... ) ); + template<class... T> using fn = 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>...>>; + using R = mp_unique<mp_product<Qret<F>::template fn, 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 )... ); } @@ -880,14 +880,14 @@

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

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

@@ -896,10 +896,10 @@ -
template<class Q, class... T> using mp_invoke = typename Q::template invoke<T...>;
+
template<class Q, class... T> using mp_invoke = typename Q::template fn<T...>;
 

- mp_invoke<Q, T...> evaluates the nested template invoke of a quoted metafunction. mp_invoke<mp_quote<F>, T...> + mp_invoke<Q, T...> evaluates the nested template fn of a quoted metafunction. mp_invoke<mp_quote<F>, T...> is an alias for F<T...>. mp_invoke<mp_quote<F, T...>, U...> is an alias for F<T..., U...>.

@@ -1688,7 +1688,7 @@ - +

Last revised: March 18, 2017 at 18:33:25 GMT

Last revised: March 20, 2017 at 14:09:13 GMT


diff --git a/doc/mp11/definitions.qbk b/doc/mp11/definitions.qbk index 9a6cd8d..5974e42 100644 --- a/doc/mp11/definitions.qbk +++ b/doc/mp11/definitions.qbk @@ -18,11 +18,11 @@ A /metafunction/ is a class template or a template alias whose parameters are al template using F2 = T*; template using F3 = std::integral_constant; -A /quoted metafunction/ is a class with a public metafunction called `invoke`, for example +A /quoted metafunction/ is a class with a public metafunction called `fn`, for example - struct Q1 { template using invoke = void; }; - struct Q2 { template using invoke = T*; }; - struct Q3 { template using invoke = std::integral_constant; }; + struct Q1 { template using fn = void; }; + struct Q2 { template using fn = T*; }; + struct Q3 { template using fn = 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 diff --git a/doc/mp11/examples.qbk b/doc/mp11/examples.qbk index 1b5a367..ce93678 100644 --- a/doc/mp11/examples.qbk +++ b/doc/mp11/examples.qbk @@ -107,14 +107,14 @@ We'll first define a helper quoted metafunction `Qret` that returns the resul template struct Qret { - template using invoke = decltype( std::declval()( std::declval()... ) ); + template using fn = 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...>; + using R = mp_product::template fn, 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`. @@ -123,7 +123,7 @@ One more step remains. Suppose that, as above, we're passing two variants of typ `[]( 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...>>; + using R = mp_unique::template fn, std::remove_reference_t...>>; and we're done: @@ -138,12 +138,12 @@ and we're done: template struct Qret { - template using invoke = decltype( std::declval()( std::declval()... ) ); + template using fn = decltype( std::declval()( std::declval()... ) ); }; template auto rvisit( F&& f, V&&... v ) { - using R = mp_unique::template invoke, std::remove_reference_t...>>; + using R = mp_unique::template fn, std::remove_reference_t...>>; return std::visit( [&]( auto&&... x ){ return R( std::forward(f)( std::forward(x)... ) ); }, std::forward( v )... ); } diff --git a/doc/mp11/utility.qbk b/doc/mp11/utility.qbk index 79c7c20..ae51f85 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 invoke = F; + template using fn = F; }; -`mp_quote` transforms the template `F` into a type. In the common case `mp_quote`, the nested template `invoke` of the result is an alias for `F`; -otherwise, `invoke` is an alias for `F`, allowing partial application. +`mp_quote` transforms the template `F` into a type. In the common case `mp_quote`, the nested template `fn` of the result is an alias for `F`; +otherwise, `fn` is an alias for `F`, allowing partial application. [endsect] [section `mp_invoke`] - template using mp_invoke = typename Q::template invoke; + template using mp_invoke = typename Q::template fn; -`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`. +`mp_invoke` evaluates the nested template `fn` of a quoted metafunction. `mp_invoke, T...>` is an alias for `F`. `mp_invoke, U...>` is an alias for `F`. [endsect] [endsect] diff --git a/include/boost/mp11/algorithm.hpp b/include/boost/mp11/algorithm.hpp index 4a6cafe..2f81789 100644 --- a/include/boost/mp11/algorithm.hpp +++ b/include/boost/mp11/algorithm.hpp @@ -290,23 +290,47 @@ template using mp_at = typename detail::mp_at_impl::type namespace detail { +template struct mp_take_c_impl; + +template class L, class... T> struct mp_take_c_impl, 0> +{ + using type = L<>; +}; + +template class L, class T1, class... T> struct mp_take_c_impl, 1> +{ + using type = L; +}; + +template class L, class T1, class T2, class... T> struct mp_take_c_impl, 2> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class... T> struct mp_take_c_impl, 3> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class... T> struct mp_take_c_impl, 4> +{ + using type = L; +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class... T, std::size_t N> struct mp_take_c_impl, N, typename std::enable_if= 5>::type> +{ + using type = mp_append, typename mp_take_c_impl, N-5>::type>; +}; + template struct mp_take_impl { static_assert( N::value >= 0, "mp_take: N must not be negative" ); - - using _map = mp_transform>, L>; - - template using _f = mp_second>; - - using _ind = mp_iota_c; - - using type = mp_assign>; + using type = typename mp_take_c_impl::type; }; } // namespace detail -template using mp_take_c = typename detail::mp_take_impl>::type; - +template using mp_take_c = typename detail::mp_take_c_impl::type; template using mp_take = typename detail::mp_take_impl::type; // mp_replace diff --git a/include/boost/mp11/utility.hpp b/include/boost/mp11/utility.hpp index 0f34d3f..78b5a9a 100644 --- a/include/boost/mp11/utility.hpp +++ b/include/boost/mp11/utility.hpp @@ -106,7 +106,16 @@ template class F, class... T> using mp_defer = mp_if class F, class... T> struct mp_quote { - template using invoke = F; +private: + + template struct _fn { using type = F; }; + +public: + + // the indirection through _fn works around the language inability + // to expand T.. to expand into a fixed parameter list of an alias template + + template using fn = typename _fn::type; }; // mp_unquote @@ -115,7 +124,7 @@ namespace detail template struct mp_invoke_impl { - using type = typename Q::template invoke; + using type = typename Q::template fn; }; template class F, class... T, class... U> struct mp_invoke_impl, U...> diff --git a/test/mp_invoke.cpp b/test/mp_invoke.cpp index 16ec66e..766e6bd 100644 --- a/test/mp_invoke.cpp +++ b/test/mp_invoke.cpp @@ -17,22 +17,27 @@ using boost::mp11::mp_size_t; struct Q1 { - template using invoke = void; + template using fn = void; }; struct Q2 { - template class invoke; + template class fn; }; struct Q3 { - template using invoke = mp_size_t; + template using fn = mp_size_t; }; struct Q4 { - template using invoke = T1; + template using fn = T1; +}; + +struct Q5 +{ + template using fn = T2; }; int main() @@ -41,9 +46,9 @@ 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, 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, Q2::fn<>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Q2::fn>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, Q2::fn>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<0>>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_size_t<1>>)); @@ -52,5 +57,7 @@ int main() BOOST_TEST_TRAIT_TRUE((std::is_same, int>)); BOOST_TEST_TRAIT_TRUE((std::is_same, int[]>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, float>)); + return boost::report_errors(); } diff --git a/test/mp_quote.cpp b/test/mp_quote.cpp index f05a91f..29bb317 100644 --- a/test/mp_quote.cpp +++ b/test/mp_quote.cpp @@ -24,7 +24,7 @@ struct D1: B {}; struct D2: B {}; struct ND {}; -template using is_base_of_t = typename std::is_base_of::type; +template using is_base_of_t = typename std::is_base_of::type; int main() { @@ -54,10 +54,11 @@ int main() { 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, <= 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 @@ -71,7 +72,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 diff --git a/test/mp_take.cpp b/test/mp_take.cpp index 6648ccf..781531d 100644 --- a/test/mp_take.cpp +++ b/test/mp_take.cpp @@ -49,6 +49,11 @@ int main() BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); + + using L3 = mp_list; + + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_list>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, mp_list>)); } { @@ -72,6 +77,11 @@ int main() BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); + + using L3 = std::tuple; + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::tuple>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>, std::tuple>)); } {