1
0
forked from boostorg/mp11

Change mp_and/mp_or to a SFINAE-based implementation

This commit is contained in:
Peter Dimov
2017-05-23 23:25:30 +03:00
parent dc0faed438
commit 07cac40f3d
5 changed files with 118 additions and 58 deletions

View File

@@ -2164,12 +2164,15 @@
</pre>
<p>
<code class="computeroutput"><span class="identifier">mp_and</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...&gt;</span></code>
is an alias for the first type <code class="computeroutput"><span class="identifier">U</span></code>
is an alias for <code class="computeroutput"><span class="identifier">mp_false</span></code>
if there exists a type <code class="computeroutput"><span class="identifier">U</span></code>
in <code class="computeroutput"><span class="identifier">T</span><span class="special">...</span></code>
for which <code class="computeroutput"><span class="identifier">mp_to_bool</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;</span></code>
is <code class="computeroutput"><span class="identifier">mp_false</span></code>. If no such
type exists, the last one is returned. <code class="computeroutput"><span class="identifier">mp_and</span><span class="special">&lt;&gt;</span></code> is <code class="computeroutput"><span class="identifier">mp_true</span></code>.
Similar to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">conjunction</span></code> in C++17.
is <code class="computeroutput"><span class="identifier">mp_false</span></code>. <code class="computeroutput"><span class="identifier">mp_to_bool</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;</span></code>
is not evaluated for types after <code class="computeroutput"><span class="identifier">U</span></code>.
If no such type exists, <code class="computeroutput"><span class="identifier">mp_and</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...&gt;</span></code> is an alias for <code class="computeroutput"><span class="identifier">mp_true</span></code>.
(<code class="computeroutput"><span class="identifier">mp_and</span><span class="special">&lt;&gt;</span></code>
is <code class="computeroutput"><span class="identifier">mp_true</span></code>.)
</p>
</div>
<div class="section">
@@ -2189,7 +2192,7 @@
is an error because <code class="computeroutput"><span class="keyword">void</span></code> does
not have a nested <code class="computeroutput"><span class="identifier">value</span></code>.
The upside is that <code class="computeroutput"><span class="identifier">mp_all</span></code>
is faster.
is faster on legacy compilers.
</p>
</div>
<div class="section">
@@ -2200,12 +2203,15 @@
</pre>
<p>
<code class="computeroutput"><span class="identifier">mp_or</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...&gt;</span></code>
is an alias for the first type <code class="computeroutput"><span class="identifier">U</span></code>
is an alias for <code class="computeroutput"><span class="identifier">mp_true</span></code>
if there exists a type <code class="computeroutput"><span class="identifier">U</span></code>
in <code class="computeroutput"><span class="identifier">T</span><span class="special">...</span></code>
for which <code class="computeroutput"><span class="identifier">mp_to_bool</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;</span></code>
is <code class="computeroutput"><span class="identifier">mp_true</span></code>. If no such
type exists, the last one is returned. <code class="computeroutput"><span class="identifier">mp_or</span><span class="special">&lt;&gt;</span></code> is <code class="computeroutput"><span class="identifier">mp_false</span></code>.
Similar to <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">disjunction</span></code> in C++17.
is <code class="computeroutput"><span class="identifier">mp_true</span></code>. <code class="computeroutput"><span class="identifier">mp_to_bool</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">&gt;</span></code>
is not evaluated for types after <code class="computeroutput"><span class="identifier">U</span></code>.
If no such type exists, <code class="computeroutput"><span class="identifier">mp_or</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...&gt;</span></code> is an alias for <code class="computeroutput"><span class="identifier">mp_false</span></code>.
(<code class="computeroutput"><span class="identifier">mp_or</span><span class="special">&lt;&gt;</span></code>
is <code class="computeroutput"><span class="identifier">mp_false</span></code>.)
</p>
</div>
<div class="section">
@@ -2444,7 +2450,7 @@
</div>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><p><small>Last revised: May 23, 2017 at 17:37:57 GMT</small></p></td>
<td align="left"><p><small>Last revised: May 23, 2017 at 20:23:39 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td>
</tr></table>
<hr>

View File

@@ -11,8 +11,9 @@
[section `mp_and<T...>`]
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.
`mp_and<T...>` is an alias for `mp_false` if there exists a type `U` in `T...` for which `mp_to_bool<U>` 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`.)
[endsect]
[section `mp_all<T...>`]
@@ -20,14 +21,15 @@ If no such type exists, the last one is returned. `mp_and<>` is `mp_true`. Simil
`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.
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<T...>`]
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.
`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`.)
[endsect]
[section `mp_any<T...>`]

View File

@@ -19,10 +19,10 @@ namespace boost
namespace mp11
{
// mp_all<T...>
template<class... T> using mp_all = mp_bool< mp_count_if< mp_list<T...>, mp_to_bool >::value == sizeof...(T) >;
// mp_and<T...>, mp_all<T...>
#if BOOST_WORKAROUND( BOOST_MSVC, < 1900 )
// mp_and<T...>
namespace detail
{
@@ -30,7 +30,7 @@ template<class... T> struct mp_and_impl;
} // namespace detail
template<class... T> using mp_and = typename detail::mp_and_impl<T...>::type;
template<class... T> using mp_and = mp_to_bool< typename detail::mp_and_impl<T...>::type >;
namespace detail
{
@@ -52,10 +52,36 @@ template<class T1, class... T> struct mp_and_impl<T1, T...>
} // namespace detail
// mp_any<T...>
template<class... T> using mp_any = mp_bool< mp_count_if< mp_list<T...>, mp_to_bool >::value != 0 >;
template<class... T> using mp_all = mp_bool< mp_count_if< mp_list<T...>, mp_to_bool >::value == sizeof...(T) >;
#else
namespace detail
{
template<class L, class E = void> struct mp_and_impl
{
using type = mp_false;
};
void mp_and_impl_f(...);
template<class... T> struct mp_and_impl< mp_list<T...>, decltype( mp_and_impl_f( mp_if<T, int>()... ) ) >
{
using type = mp_true;
};
} // namespace detail
template<class... T> using mp_and = typename detail::mp_and_impl<mp_list<T...>>::type;
template<class... T> using mp_all = typename detail::mp_and_impl<mp_list<T...>>::type;
#endif
// mp_or<T...>, mp_any<T...>
#if BOOST_WORKAROUND( BOOST_MSVC, < 1900 )
// mp_or<T...>
namespace detail
{
@@ -63,7 +89,7 @@ template<class... T> struct mp_or_impl;
} // namespace detail
template<class... T> using mp_or = typename detail::mp_or_impl<T...>::type;
template<class... T> using mp_or = mp_to_bool< typename detail::mp_or_impl<T...>::type >;
namespace detail
{
@@ -85,6 +111,32 @@ template<class T1, class... T> struct mp_or_impl<T1, T...>
} // namespace detail
template<class... T> using mp_any = mp_bool< mp_count_if< mp_list<T...>, mp_to_bool >::value != 0 >;
#else
namespace detail
{
template<class L, class E = void> struct mp_or_impl
{
using type = mp_true;
};
void mp_and_impl_f(...);
template<class... T> struct mp_or_impl< mp_list<T...>, decltype( mp_and_impl_f( mp_if<mp_not<T>, int>()... ) ) >
{
using type = mp_false;
};
} // namespace detail
template<class... T> using mp_or = typename detail::mp_or_impl<mp_list<T...>>::type;
template<class... T> using mp_any = typename detail::mp_or_impl<mp_list<T...>>::type;
#endif
// mp_same<T...>
namespace detail
{

View File

@@ -25,23 +25,23 @@ int main()
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_false>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<-7>>, mp_int<-7>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<0>>, mp_int<0>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<-7>>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<0>>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<7>>, mp_size_t<7>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<0>>, mp_size_t<0>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<7>>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<0>>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true, mp_true>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true, mp_false>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_false, void>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<-4>, mp_int<5>>, mp_int<5>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<-4>, mp_int<0>>, mp_int<0>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<0>, void>, mp_int<0>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<-4>, mp_int<5>>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<-4>, mp_int<0>>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<0>, void>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<7>, mp_size_t<8>>, mp_size_t<8>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<7>, mp_size_t<0>>, mp_size_t<0>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<0>, void>, mp_size_t<0>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<7>, mp_size_t<8>>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<7>, mp_size_t<0>>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<0>, void>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true, mp_true, mp_true>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true, mp_true, mp_false>, mp_false>));
@@ -54,11 +54,11 @@ int main()
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_true, mp_false, void, void>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_false, void, void, void>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<1>, mp_int<2>, mp_int<-11>, mp_int<14>>, mp_int<14>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<1>, mp_int<0>, void, void>, mp_int<0>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<1>, mp_int<2>, mp_int<-11>, mp_int<14>>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_int<1>, mp_int<0>, void, void>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<1>, 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_and<mp_size_t<1>, mp_size_t<2>, mp_size_t<0>, void, void>, mp_size_t<0>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_and<mp_size_t<1>, 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_and<mp_size_t<1>, mp_size_t<2>, mp_size_t<0>, void, void>, mp_false>));
return boost::report_errors();
}

View File

@@ -25,23 +25,23 @@ int main()
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_true>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<-7>>, mp_int<-7>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>>, mp_int<0>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<-7>>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<7>>, mp_size_t<7>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>>, mp_size_t<0>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<7>>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_true, void>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false, mp_true>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false, mp_false>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<0>>, mp_int<0>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<5>>, mp_int<5>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<-4>, void>, mp_int<-4>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<0>>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<5>>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<-4>, void>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<7>, void>, mp_size_t<7>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_size_t<4>>, mp_size_t<4>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_size_t<0>>, mp_size_t<0>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<7>, void>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_size_t<4>>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_size_t<0>>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_true, void, void>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false, mp_true, void>, mp_true>));
@@ -54,19 +54,19 @@ int main()
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false, mp_false, mp_false, mp_true>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_false, mp_false, mp_false, mp_false>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<1>, void, void, void>, mp_int<1>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<2>, void, void, void>, mp_int<2>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<0>, mp_int<3>, void, void, void>, mp_int<3>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<0>, mp_int<0>, mp_int<4>, void, void, void>, mp_int<4>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<0>, mp_int<0>, mp_int<0>, mp_int<0>>, mp_int<0>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<1>, void, void, void>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<2>, void, void, void>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<0>, mp_int<3>, void, void, void>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<0>, mp_int<0>, mp_int<4>, void, void, void>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_int<0>, mp_int<0>, mp_int<0>, mp_int<0>, mp_int<0>>, mp_false>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<1>, void, void, void>, mp_size_t<1>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_size_t<2>, void, void, void>, mp_size_t<2>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_size_t<0>, mp_size_t<3>, void, void, void>, mp_size_t<3>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, 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_or<mp_size_t<0>, 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_or<mp_size_t<1>, void, void, void>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_size_t<2>, void, void, void>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_size_t<0>, mp_size_t<3>, void, void, void>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, 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_or<mp_size_t<0>, 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_or<mp_size_t<0>, mp_int<0>, mp_false, mp_size_t<141>, void, void, void>, mp_size_t<141>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_int<0>, mp_false, mp_size_t<141>, void, void, void>, mp_true>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_or<mp_size_t<0>, mp_int<0>, mp_false>, mp_false>));
return boost::report_errors();