From 6b1a2f61562f57839205cb90b1938b9bcabff8e6 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 24 May 2017 01:37:49 +0300 Subject: [PATCH] Revert mp_or; add mp_void; update documentation --- doc/html/mp11.html | 50 +++++++++++++++++++++++++-------- doc/mp11/function.qbk | 33 +++++++++++++++++++--- include/boost/mp11/function.hpp | 49 +++++++++++--------------------- 3 files changed, 85 insertions(+), 47 deletions(-) diff --git a/doc/html/mp11.html b/doc/html/mp11.html index d671040..61b6950 100644 --- a/doc/html/mp11.html +++ b/doc/html/mp11.html @@ -166,6 +166,7 @@
Helper Metafunctions, <boost/mp11/function.hpp>
+
mp_void<T...>
mp_and<T...>
mp_all<T...>
mp_or<T...>
@@ -2158,6 +2159,16 @@
+
template<class... T> using mp_void = void;
+
+

+ Same as std::void_t from C++17. +

+
+
+
template<class... T> using mp_and = /*...*/;
@@ -2168,12 +2179,17 @@
           if there exists a type U
           in T...
           for which mp_to_bool<U>
-          is mp_false. mp_to_bool<U>
+          is not mp_true. 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.)
         

+
using R1 = mp_and<mp_true, mp_true>;   // mp_true
+using R2 = mp_and<mp_false, void>;     // mp_false, void is not reached
+using R3 = mp_and<mp_false, mp_false>; // mp_false
+using R4 = mp_and<void, mp_true>;      // mp_false (!)
+

@@ -2194,6 +2210,11 @@ The upside is that mp_all is faster on legacy compilers.

+
using R1 = mp_and<mp_true, mp_true>;   // mp_true
+using R2 = mp_and<mp_false, void>;     // compile-time error
+using R3 = mp_and<mp_false, mp_false>; // mp_false
+using R4 = mp_and<void, mp_true>;      // compile-time error
+

@@ -2203,16 +2224,18 @@

mp_or<T...> - is an alias for mp_true - if there exists a type U - in T... - for which mp_to_bool<U> - 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.) + applies mp_to_bool to the + types in T..., + in order. If the result of an application is mp_true, + mp_or returns mp_true. If all results are mp_false, returns mp_false. + mp_or<> + is mp_false.

+
using R1 = mp_or<mp_true, mp_false>;   // mp_true
+using R2 = mp_or<mp_true, void>;       // mp_true, void is not reached
+using R3 = mp_or<mp_false, mp_false>;  // mp_false
+using R4 = mp_or<void, mp_true>;       // compile-time error
+

@@ -2228,6 +2251,11 @@ otherwise. Same as mp_or, but does not perform short-circuit evaluation.

+
using R1 = mp_any<mp_true, mp_false>;  // mp_true
+using R2 = mp_any<mp_true, void>;      // compile-time error
+using R3 = mp_any<mp_false, mp_false>; // mp_false
+using R4 = mp_any<void, mp_true>;      // compile-time error
+

@@ -2450,7 +2478,7 @@

- +

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

Last revised: May 23, 2017 at 22:20:27 GMT


diff --git a/doc/mp11/function.qbk b/doc/mp11/function.qbk index fca535c..20700bf 100644 --- a/doc/mp11/function.qbk +++ b/doc/mp11/function.qbk @@ -8,12 +8,23 @@ [section:function Helper Metafunctions, ``] +[section `mp_void`] + template using mp_void = void; + +Same as `std::void_t` from C++17. +[endsect] + [section `mp_and`] template using mp_and = /*...*/; -`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_and` is an alias for `mp_false` if there exists a type `U` in `T...` for which `mp_to_bool` is not `mp_true`. `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`.) + + using R1 = mp_and; // mp_true + using R2 = mp_and; // mp_false, void is not reached + using R3 = mp_and; // mp_false + using R4 = mp_and; // mp_false (!) [endsect] [section `mp_all`] @@ -22,14 +33,23 @@ `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 on legacy compilers. + + using R1 = mp_and; // mp_true + using R2 = mp_and; // compile-time error + using R3 = mp_and; // mp_false + using R4 = mp_and; // compile-time error [endsect] [section `mp_or`] template using mp_or = /*...*/; -`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`.) +`mp_or` applies `mp_to_bool` to the types in `T...`, in order. If the result of an application is `mp_true`, `mp_or` +returns `mp_true`. If all results are `mp_false`, returns `mp_false`. `mp_or<>` is `mp_false`. + + using R1 = mp_or; // mp_true + using R2 = mp_or; // mp_true, void is not reached + using R3 = mp_or; // mp_false + using R4 = mp_or; // compile-time error [endsect] [section `mp_any`] @@ -37,6 +57,11 @@ is an error because `void` does not have a nested `value`. The upside is that `m `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. + + using R1 = mp_any; // mp_true + using R2 = mp_any; // compile-time error + using R3 = mp_any; // mp_false + using R4 = mp_any; // compile-time error [endsect] [section `mp_same`] diff --git a/include/boost/mp11/function.hpp b/include/boost/mp11/function.hpp index 04d9dae..5b6ef9f 100644 --- a/include/boost/mp11/function.hpp +++ b/include/boost/mp11/function.hpp @@ -19,9 +19,22 @@ namespace boost namespace mp11 { +// mp_void +namespace detail +{ + +template struct mp_void_impl +{ + using type = void; +}; + +} // namespace detail + +template using mp_void = typename detail::mp_void_impl::type; + // mp_and, mp_all -#if BOOST_WORKAROUND( BOOST_MSVC, < 1900 ) +#if BOOST_WORKAROUND( BOOST_MSVC, < 1910 ) namespace detail { @@ -64,9 +77,7 @@ 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()... ) ) > +template struct mp_and_impl< mp_list, mp_void...> > { using type = mp_true; }; @@ -78,10 +89,7 @@ template using mp_all = typename detail::mp_and_impl>: #endif -// mp_or, mp_any - -#if BOOST_WORKAROUND( BOOST_MSVC, < 1900 ) - +// mp_or namespace detail { @@ -111,32 +119,9 @@ template struct mp_or_impl } // namespace detail +// mp_any 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 {