diff --git a/doc/html/mp11.html b/doc/html/mp11.html index b1cc0c6..4a64ff4 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -157,6 +157,14 @@
mp_or<T...>
mp_any<T...>
+
Bind, <boost/mp11/bind.hpp>
+
+
mp_arg<I>
+
_1, + ..., _9
+
mp_bind<F, + T...>
+
Integer Sequences, <boost/integer_sequence.hpp>
@@ -215,7 +223,7 @@ Definitions

- A list is a — possibly but not necessarily variadic — template + A list is a — usually but not necessarily variadic — template class whose parameters are all types, for example mp_list<char[], void>, mp_list<>, @@ -251,6 +259,16 @@

struct N { static int constexpr value = 2; };
 
+

+ A set is a list whose elements are unique. +

+

+ A map is a list of lists, the inner lists having at least + one element (the key.) The keys of the map must be unique. For example, +

+
using M1 = std::tuple<std::pair<int, int*>, std::pair<float, float*>, std::pair<void, void*>>;
+using M2 = mp_list<mp_list<int, int*>, mp_list<float>, mp_list<char, char[1], char[2]>>;
+

@@ -1609,6 +1627,62 @@

+
+ +
template<std::size_t I> struct mp_arg;
+
+

+ mp_arg<I> + is a quoted metafunction whose nested template fn<T...> returns the I-th + zero-based element of T.... +

+
+
+ +
using _1 = mp_arg<0>;
+using _2 = mp_arg<1>;
+using _3 = mp_arg<2>;
+using _4 = mp_arg<3>;
+using _5 = mp_arg<4>;
+using _6 = mp_arg<5>;
+using _7 = mp_arg<6>;
+using _8 = mp_arg<7>;
+using _9 = mp_arg<8>;
+
+

+ _1 to _9 + are placeholder types, the equivalent to the placeholders of boost::bind. +

+
+
+ +
template<template<class...> class F, class... T> struct mp_bind;
+
+

+ mp_bind<F, T...> is a quoted metafunction that implements + the type-based equivalent of boost::bind. + Its nested template fn<U...> returns F<V...>, where V... is T... with the placeholders replaced by the + corresponding element of U... and the mp_bind + expressions replaced with their corresponding evaluations against U.... +

+

+ For example, mp_bind<F, int, _2, mp_bind<G, _1>>::fn<float, void> + is F<int, void, G<float>>. +

+
+
+
- +

Last revised: March 25, 2017 at 01:01:08 GMT

Last revised: April 01, 2017 at 16:43:16 GMT


diff --git a/doc/mp11.qbk b/doc/mp11.qbk index f1f55e9..db40f52 100644 --- a/doc/mp11.qbk +++ b/doc/mp11.qbk @@ -38,6 +38,7 @@ The contents of the library are in namespace `boost::mp11`, unless specified oth [include mp11/set.qbk] [include mp11/map.qbk] [include mp11/function.qbk] +[include mp11/bind.qbk] [include mp11/integer_sequence.qbk] [include mp11/tuple_for_each.qbk] diff --git a/doc/mp11/bind.qbk b/doc/mp11/bind.qbk new file mode 100644 index 0000000..0278122 --- /dev/null +++ b/doc/mp11/bind.qbk @@ -0,0 +1,41 @@ +[/ + / 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:bind Bind, ``] + +[section `mp_arg`] + template struct mp_arg; + +`mp_arg` is a quoted metafunction whose nested template `fn` returns the `I`-th zero-based element of `T...`. +[endsect] + +[section `_1`, ..., `_9`] + using _1 = mp_arg<0>; + using _2 = mp_arg<1>; + using _3 = mp_arg<2>; + using _4 = mp_arg<3>; + using _5 = mp_arg<4>; + using _6 = mp_arg<5>; + using _7 = mp_arg<6>; + using _8 = mp_arg<7>; + using _9 = mp_arg<8>; + +`_1` to `_9` are placeholder types, the equivalent to the placeholders of `boost::bind`. +[endsect] + +[section `mp_bind`] + template class F, class... T> struct mp_bind; + +`mp_bind` is a quoted metafunction that implements the type-based equivalent of `boost::bind`. Its nested +template `fn` returns `F`, where `V...` is `T...` with the placeholders replaced by the corresponding element +of `U...` and the `mp_bind` expressions replaced with their corresponding evaluations against `U...`. + +For example, `mp_bind>::fn` is `F>`. +[endsect] + +[endsect] diff --git a/doc/mp11/definitions.qbk b/doc/mp11/definitions.qbk index 5974e42..23586d7 100644 --- a/doc/mp11/definitions.qbk +++ b/doc/mp11/definitions.qbk @@ -8,7 +8,7 @@ [section Definitions] -A /list/ is a '''—''' possibly but not necessarily variadic '''—''' template class whose parameters are all types, +A /list/ is a '''—''' usually 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`, @@ -29,4 +29,11 @@ An /integral constant type/ is a class with a public member `value` that is an i struct N { static int constexpr value = 2; }; +A /set/ is a list whose elements are unique. + +A /map/ is a list of lists, the inner lists having at least one element (the key.) The keys of the map must be unique. For example, + + using M1 = std::tuple, std::pair, std::pair>; + using M2 = mp_list, mp_list, mp_list>; + [endsect] diff --git a/include/boost/mp11.hpp b/include/boost/mp11.hpp index 4060a3f..4241337 100644 --- a/include/boost/mp11.hpp +++ b/include/boost/mp11.hpp @@ -15,5 +15,6 @@ #include #include #include +#include #endif // #ifndef BOOST_MP11_HPP_INCLUDED diff --git a/include/boost/mp11/algorithm.hpp b/include/boost/mp11/algorithm.hpp index cda0eb7..503f5cd 100644 --- a/include/boost/mp11/algorithm.hpp +++ b/include/boost/mp11/algorithm.hpp @@ -44,6 +44,16 @@ template using mp_assign = typename detail::mp_assign_impl template using mp_clear = mp_assign>; +// mp_fold forward declaration +namespace detail +{ + +template class F> struct mp_fold_impl; + +} // namespace detail + +template class F> using mp_fold = typename detail::mp_fold_impl::type; + // mp_transform namespace detail { @@ -71,69 +81,46 @@ template class F, template class L1, class... T1, t template class F, class... L> using mp_transform = typename detail::mp_transform_impl::type; +namespace detail +{ + +template class F, template class L1, class... T1, template class L2, class... T2, template class L3, class... T3, template class L4, class... T4, class... L> struct mp_transform_impl, L2, L3, L4, L...> +{ + static_assert( sizeof...(T1) == sizeof...(T2) && sizeof...(T1) == sizeof...(T3) && sizeof...(T1) == sizeof...(T4), "The arguments of mp_transform should be of the same size" ); + + using A1 = L1...>; + + template using _f = mp_transform; + + using A2 = mp_fold, A1, _f>; + + template using _g = mp_apply; + + using type = mp_transform<_g, A2>; +}; + +} // namespace detail + // mp_transform_if namespace detail { -/* template class P, template class F, class... L> struct mp_transform_if_impl { - // error: pack expansion used as argument for non-pack parameter of alias template - template using _f = mp_eval_if>, mp_first>, F, U...>; + // the stupid quote-unquote dance avoids "pack expansion used as argument for non-pack parameter of alias template" +#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) + + template struct _f_ { using type = mp_eval_if, U...>>, mp_first>, mp_quote::template fn, U...>; }; + template using _f = typename _f_::type; + +#else + + template using _f = mp_eval_if, U...>>, mp_first>, mp_quote::template fn, U...>; + +#endif + using type = mp_transform<_f, L...>; }; -*/ - -template class P, template class F, class... L> struct mp_transform_if_impl; - -template class P, template class F, template class L, class... T> struct mp_transform_if_impl> -{ -#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) - - template struct _f { using type = mp_eval_if>, U, F, U>; }; - using type = L::type...>; - -#else - - template using _f = mp_eval_if>, U, F, U>; - using type = L<_f...>; - -#endif -}; - -template class P, template class F, template class L1, class... T1, template class L2, class... T2> struct mp_transform_if_impl, L2> -{ - static_assert( sizeof...(T1) == sizeof...(T2), "The arguments of mp_transform_if should be of the same size" ); - -#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) - - template struct _f { using type = mp_eval_if>, U1, F, U1, U2>; }; - using type = L1::type...>; - -#else - - template using _f = mp_eval_if>, U1, F, U1, U2>; - using type = L1<_f...>; - -#endif -}; - -template class P, template class F, template class L1, class... T1, template class L2, class... T2, template class L3, class... T3> struct mp_transform_if_impl, L2, L3> -{ - static_assert( sizeof...(T1) == sizeof...(T2) && sizeof...(T1) == sizeof...(T3), "The arguments of mp_transform_if should be of the same size" ); - -#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) - - template struct _f { using type = mp_eval_if>, U1, F, U1, U2, U3>; }; - using type = L1::type...>; - -#else - - template using _f = mp_eval_if>, U1, F, U1, U2, U3>; - using type = L1<_f...>; - -#endif -}; } // namespace detail @@ -753,8 +740,6 @@ template class L, class T1, class T2, class T3, class T4, cla } // namespace detail -template class F> using mp_fold = typename detail::mp_fold_impl::type; - // mp_reverse_fold namespace detail { diff --git a/include/boost/mp11/bind.hpp b/include/boost/mp11/bind.hpp new file mode 100644 index 0000000..f7febf5 --- /dev/null +++ b/include/boost/mp11/bind.hpp @@ -0,0 +1,64 @@ +#ifndef BOOST_MP11_BIND_HPP_INCLUDED +#define BOOST_MP11_BIND_HPP_INCLUDED + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + +#include +#include + +namespace boost +{ +namespace mp11 +{ + +template struct mp_arg +{ + template using fn = mp_at_c, I>; +}; + +using _1 = mp_arg<0>; +using _2 = mp_arg<1>; +using _3 = mp_arg<2>; +using _4 = mp_arg<3>; +using _5 = mp_arg<4>; +using _6 = mp_arg<5>; +using _7 = mp_arg<6>; +using _8 = mp_arg<7>; +using _9 = mp_arg<8>; + +template class F, class... T> struct mp_bind; + +namespace detail +{ + +template struct eval_bound_arg +{ + using type = V; +}; + +template struct eval_bound_arg, T...> +{ + using type = typename mp_arg::template fn; +}; + +template class F, class... U, class... T> struct eval_bound_arg, T...> +{ + using type = typename mp_bind::template fn; +}; + +} // namespace detail + +template class F, class... T> struct mp_bind +{ + template using fn = F::type...>; +}; + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_BIND_HPP_INCLUDED diff --git a/include/boost/mp11/function.hpp b/include/boost/mp11/function.hpp index e714aa0..571a24b 100644 --- a/include/boost/mp11/function.hpp +++ b/include/boost/mp11/function.hpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace boost { @@ -84,6 +85,26 @@ template struct mp_or_impl } // namespace detail +// mp_same +namespace detail +{ + +template struct mp_same_impl; + +template<> struct mp_same_impl<> +{ + using type = mp_true; +}; + +template struct mp_same_impl +{ + using type = mp_all...>; +}; + +} // namespace detail + +template using mp_same = typename detail::mp_same_impl::type; + } // namespace mp11 } // namespace boost diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 4f68b59..3bfaec6 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -94,6 +94,7 @@ run mp_all.cpp : : : $(REQ) ; run mp_and.cpp : : : $(REQ) ; run mp_any.cpp : : : $(REQ) ; run mp_or.cpp : : : $(REQ) ; +run mp_same.cpp : : : $(REQ) ; # map run mp_map_find.cpp : : : $(REQ) ; @@ -102,3 +103,6 @@ run mp_map_insert.cpp : : : $(REQ) ; run mp_map_replace.cpp : : : $(REQ) ; run mp_map_erase.cpp : : : $(REQ) ; run mp_map_update.cpp : : : $(REQ) ; + +# bind +run mp_bind.cpp : : : $(REQ) ; diff --git a/test/mp_bind.cpp b/test/mp_bind.cpp new file mode 100644 index 0000000..19edf31 --- /dev/null +++ b/test/mp_bind.cpp @@ -0,0 +1,106 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + + +#include +#include +#include +#include +#include +#include +#include + +struct X1 {}; +struct X2 {}; +struct X3 {}; +struct X4 {}; +struct X5 {}; +struct X6 {}; +struct X7 {}; +struct X8 {}; +struct X9 {}; + +template using add_pointer = typename std::add_pointer::type; + +int main() +{ + using namespace boost::mp11; + + BOOST_TEST_TRAIT_TRUE((std::is_same<_1::fn, X1>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<_1::fn, X1>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<_2::fn, X2>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<_2::fn, X2>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<_3::fn, X3>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<_3::fn, X3>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<_4::fn, X4>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<_4::fn, X4>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<_5::fn, X5>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<_5::fn, X5>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<_6::fn, X6>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<_6::fn, X6>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<_7::fn, X7>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<_7::fn, X7>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<_8::fn, X8>)); + BOOST_TEST_TRAIT_TRUE((std::is_same<_8::fn, X8>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same<_9::fn, X9>)); + + // + + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X1*>)); + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X1*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X2*>)); + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X2*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X3*>)); + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X3*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X4*>)); + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X4*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X5*>)); + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X5*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X6*>)); + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X6*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X7*>)); + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X7*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X8*>)); + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X8*>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same::fn, X9*>)); + + // + + BOOST_TEST_TRAIT_TRUE((std::is_same< + mp_bind, + mp_bind, + mp_bind, + mp_bind, + mp_bind, + mp_bind, + mp_bind, + mp_bind, + mp_bind + >::fn, std::tuple>)); + + // + + return boost::report_errors(); +} diff --git a/test/mp_same.cpp b/test/mp_same.cpp new file mode 100644 index 0000000..5b642ae --- /dev/null +++ b/test/mp_same.cpp @@ -0,0 +1,33 @@ + +// Copyright 2017 Peter Dimov. +// +// Distributed under the Boost Software License, Version 1.0. +// +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt + + +#include +#include +#include + +int main() +{ + using boost::mp11::mp_same; + using boost::mp11::mp_true; + using boost::mp11::mp_false; + + 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_true>)); + 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_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_false>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_false>)); + + return boost::report_errors(); +} diff --git a/test/mp_transform.cpp b/test/mp_transform.cpp index 6782278..ed6f1dd 100644 --- a/test/mp_transform.cpp +++ b/test/mp_transform.cpp @@ -29,6 +29,15 @@ struct Z2 {}; struct Z3 {}; struct Z4 {}; +struct U1 {}; +struct U2 {}; + +struct V1 {}; +struct V2 {}; + +struct W1 {}; +struct W2 {}; + template using add_pointer = typename std::add_pointer::type; template using is_same = typename std::is_same::type; @@ -81,5 +90,16 @@ int main() // + using L8 = std::pair; + using L9 = std::pair; + using L10 = std::pair; + using L11 = std::pair; + + BOOST_TEST_TRAIT_TRUE((std::is_same, std::pair, std::tuple>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::pair, std::tuple>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same, std::pair, std::tuple>>)); + + // + return boost::report_errors(); } diff --git a/test/mp_transform_if.cpp b/test/mp_transform_if.cpp index 89292dd..048909a 100644 --- a/test/mp_transform_if.cpp +++ b/test/mp_transform_if.cpp @@ -26,6 +26,8 @@ template using add_pointer = T*; template using is_not_ref = mp_not>; template using second = T2; template using third = T3; +template using fourth = T4; +template using fifth = T5; int main() { @@ -58,6 +60,14 @@ int main() BOOST_TEST_TRAIT_TRUE((std::is_same>>, std::tuple, X2&, mp_size_t<2>, X4 const&>>)); BOOST_TEST_TRAIT_TRUE((std::is_same>>, std::pair, X2&>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>>, mp_list, X2&, mp_size_t<2>, X4 const&>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>>, std::tuple, X2&, mp_size_t<2>, X4 const&>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>>, std::pair, X2&>>)); + + BOOST_TEST_TRAIT_TRUE((std::is_same>>, mp_list, X2&, mp_size_t<2>, X4 const&>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>>, std::tuple, X2&, mp_size_t<2>, X4 const&>>)); + BOOST_TEST_TRAIT_TRUE((std::is_same>>, std::pair, X2&>>)); + // return boost::report_errors();