From 07cac40f3d0e7590dda513144e9211877de04622 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 23 May 2017 23:25:30 +0300 Subject: [PATCH] Change mp_and/mp_or to a SFINAE-based implementation --- doc/html/mp11.html | 26 ++++++++----- doc/mp11/function.qbk | 12 +++--- include/boost/mp11/function.hpp | 68 +++++++++++++++++++++++++++++---- test/mp_and.cpp | 28 +++++++------- test/mp_or.cpp | 42 ++++++++++---------- 5 files changed, 118 insertions(+), 58 deletions(-) diff --git a/doc/html/mp11.html b/doc/html/mp11.html index 3cdc9d4..d671040 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -2164,12 +2164,15 @@

mp_and<T...> - is an alias for the first type U + is an alias for mp_false + if there exists a 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. + is mp_false. mp_to_bool<U> + is not evaluated for types after U. + If no such type exists, mp_and<T...> is an alias for mp_true. + (mp_and<> + is mp_true.)

@@ -2189,7 +2192,7 @@ is an error because void does not have a nested value. The upside is that mp_all - is faster. + is faster on legacy compilers.

@@ -2200,12 +2203,15 @@

mp_or<T...> - is an alias for the first type U + is an alias for mp_true + if there exists a 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. + is mp_true. mp_to_bool<U> + is not evaluated for types after U. + If no such type exists, mp_or<T...> is an alias for mp_false. + (mp_or<> + is mp_false.)

@@ -2444,7 +2450,7 @@
- +

Last revised: May 23, 2017 at 17:37:57 GMT

Last revised: May 23, 2017 at 20:23:39 GMT


diff --git a/doc/mp11/function.qbk b/doc/mp11/function.qbk index 0ccdc49..fca535c 100644 --- a/doc/mp11/function.qbk +++ b/doc/mp11/function.qbk @@ -11,8 +11,9 @@ [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. +`mp_and` is an alias for `mp_false` if there exists a type `U` in `T...` for which `mp_to_bool` is `mp_false`. +`mp_to_bool` is not evaluated for types after `U`. If no such type exists, `mp_and` is an alias for `mp_true`. +(`mp_and<>` is `mp_true`.) [endsect] [section `mp_all`] @@ -20,14 +21,15 @@ If no such type exists, the last one is returned. `mp_and<>` is `mp_true`. Simil `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. +is an error because `void` does not have a nested `value`. The upside is that `mp_all` is faster on legacy compilers. [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. +`mp_or` is an alias for `mp_true` if there exists a type `U` in `T...` for which `mp_to_bool` is `mp_true`. +`mp_to_bool` is not evaluated for types after `U`. If no such type exists, `mp_or` is an alias for `mp_false`. +(`mp_or<>` is `mp_false`.) [endsect] [section `mp_any`] diff --git a/include/boost/mp11/function.hpp b/include/boost/mp11/function.hpp index 571a24b..04d9dae 100644 --- a/include/boost/mp11/function.hpp +++ b/include/boost/mp11/function.hpp @@ -19,10 +19,10 @@ namespace boost namespace mp11 { -// mp_all -template using mp_all = mp_bool< mp_count_if< mp_list, mp_to_bool >::value == sizeof...(T) >; +// mp_and, mp_all + +#if BOOST_WORKAROUND( BOOST_MSVC, < 1900 ) -// mp_and namespace detail { @@ -30,7 +30,7 @@ template struct mp_and_impl; } // namespace detail -template using mp_and = typename detail::mp_and_impl::type; +template using mp_and = mp_to_bool< typename detail::mp_and_impl::type >; namespace detail { @@ -52,10 +52,36 @@ template struct mp_and_impl } // namespace detail -// mp_any -template using mp_any = mp_bool< mp_count_if< mp_list, mp_to_bool >::value != 0 >; +template using mp_all = mp_bool< mp_count_if< mp_list, mp_to_bool >::value == sizeof...(T) >; + +#else + +namespace detail +{ + +template struct mp_and_impl +{ + using type = mp_false; +}; + +void mp_and_impl_f(...); + +template struct mp_and_impl< mp_list, decltype( mp_and_impl_f( mp_if()... ) ) > +{ + using type = mp_true; +}; + +} // namespace detail + +template using mp_and = typename detail::mp_and_impl>::type; +template using mp_all = typename detail::mp_and_impl>::type; + +#endif + +// mp_or, mp_any + +#if BOOST_WORKAROUND( BOOST_MSVC, < 1900 ) -// mp_or namespace detail { @@ -63,7 +89,7 @@ template struct mp_or_impl; } // namespace detail -template using mp_or = typename detail::mp_or_impl::type; +template using mp_or = mp_to_bool< typename detail::mp_or_impl::type >; namespace detail { @@ -85,6 +111,32 @@ template struct mp_or_impl } // namespace detail +template using mp_any = mp_bool< mp_count_if< mp_list, mp_to_bool >::value != 0 >; + +#else + +namespace detail +{ + +template struct mp_or_impl +{ + using type = mp_true; +}; + +void mp_and_impl_f(...); + +template struct mp_or_impl< mp_list, decltype( mp_and_impl_f( mp_if, int>()... ) ) > +{ + using type = mp_false; +}; + +} // namespace detail + +template using mp_or = typename detail::mp_or_impl>::type; +template using mp_any = typename detail::mp_or_impl>::type; + +#endif + // mp_same namespace detail { diff --git a/test/mp_and.cpp b/test/mp_and.cpp index 0d3c00a..93da74a 100644 --- a/test/mp_and.cpp +++ b/test/mp_and.cpp @@ -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_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_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_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_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_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_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_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_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_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_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>>)); + 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>)); return boost::report_errors(); } diff --git a/test/mp_or.cpp b/test/mp_or.cpp index 24190cf..f88097e 100644 --- a/test/mp_or.cpp +++ b/test/mp_or.cpp @@ -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_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_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_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, 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, 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, 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, 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_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_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_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, 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, 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_size_t<141>, void, void, void>, mp_true>)); BOOST_TEST_TRAIT_TRUE((std::is_same, mp_int<0>, mp_false>, mp_false>)); return boost::report_errors();