diff --git a/include/boost/mp11/utility.hpp b/include/boost/mp11/utility.hpp index 213857d..cee33df 100644 --- a/include/boost/mp11/utility.hpp +++ b/include/boost/mp11/utility.hpp @@ -8,6 +8,8 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt +#include + namespace boost { @@ -20,7 +22,10 @@ template struct mp_identity // mp_inherit template struct mp_inherit: T... {}; -// mp_if +// mp_if, mp_if_c +namespace detail +{ + template struct mp_if_c_impl; template struct mp_if_c_impl @@ -33,11 +38,15 @@ template struct mp_if_c_impl using type = E; }; -template using mp_if_c = typename mp_if_c_impl::type; +} // namespace detail -template using mp_if = typename mp_if_c_impl( C::value ), T, E>::type; +template using mp_if_c = typename detail::mp_if_c_impl::type; +template using mp_if = typename detail::mp_if_c_impl(C::value), T, E>::type; + +// mp_eval_if, mp_eval_if_c +namespace detail +{ -// mp_eval_if template class F, class... U> struct mp_eval_if_c_impl; template class F, class... U> struct mp_eval_if_c_impl @@ -50,9 +59,36 @@ template class F, class... U> struct mp_eval_if_c_im using type = F; }; -template class F, class... U> using mp_eval_if_c = typename mp_eval_if_c_impl::type; +} // namespace detail -template class F, class... U> using mp_eval_if = typename mp_eval_if_c_impl( C::value ), T, F, U...>::type; +template class F, class... U> using mp_eval_if_c = typename detail::mp_eval_if_c_impl::type; +template class F, class... U> using mp_eval_if = typename detail::mp_eval_if_c_impl(C::value), T, F, U...>::type; + +// mp_valid +// implementation by Bruno Dutra (by the name is_evaluable) +namespace detail +{ + +template class F, class... T> struct mp_valid_impl +{ + template class G, class = G> static mp_true check(int); + template class> static mp_false check(...); + + using type = decltype(check(0)); +}; + +} // namespace detail + +template class F, class... T> using mp_valid = typename detail::mp_valid_impl::type; + +// mp_defer +template class F, class... T> struct mp_defer +{ + using type = F; +}; + +// mp_defer_if_valid +template class F, class... T> using mp_defer_if_valid = mp_if, mp_defer, mp_inherit<>>; } // namespace boost diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 395aa0d..dfff4fe 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -57,6 +57,9 @@ run mp_identity.cpp : : : $(REQ) ; run mp_inherit.cpp : : : $(REQ) ; run mp_if.cpp : : : $(REQ) ; run mp_eval_if.cpp : : : $(REQ) ; +run mp_valid.cpp : : : $(REQ) ; +run mp_defer.cpp : : : $(REQ) ; +run mp_defer_if_valid.cpp : : : $(REQ) ; # integer_sequence run integer_sequence.cpp : : : $(REQ) ; diff --git a/test/integral.cpp b/test/integral.cpp index 92e9bc4..6935aad 100644 --- a/test/integral.cpp +++ b/test/integral.cpp @@ -7,8 +7,8 @@ // http://www.boost.org/LICENSE_1_0.txt -#include #include +#include #include #include diff --git a/test/mp_defer.cpp b/test/mp_defer.cpp new file mode 100644 index 0000000..09aa771 --- /dev/null +++ b/test/mp_defer.cpp @@ -0,0 +1,26 @@ + +// Copyright 2015 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 + +template using add_pointer = T*; + +using boost::mp_defer; + +template using add_pointer_impl = mp_defer; + +int main() +{ + BOOST_TEST_TRAIT_TRUE((std::is_same::type, void*>)); + BOOST_TEST_TRAIT_TRUE((std::is_same::type, int*>)); + + return boost::report_errors(); +} diff --git a/test/mp_defer_if_valid.cpp b/test/mp_defer_if_valid.cpp new file mode 100644 index 0000000..32c449b --- /dev/null +++ b/test/mp_defer_if_valid.cpp @@ -0,0 +1,29 @@ + +// Copyright 2015 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 + +using boost::mp_defer_if_valid; +using boost::mp_identity; + +template using mp_identity_2 = typename mp_defer_if_valid::type; + +int main() +{ + using boost::mp_valid; + + BOOST_TEST_TRAIT_FALSE((mp_valid)); + BOOST_TEST_TRAIT_TRUE((mp_valid)); + BOOST_TEST_TRAIT_TRUE((std::is_same, mp_identity>)); + BOOST_TEST_TRAIT_FALSE((mp_valid)); + + return boost::report_errors(); +} diff --git a/test/mp_eval_if.cpp b/test/mp_eval_if.cpp index 2f291e9..218b8d1 100644 --- a/test/mp_eval_if.cpp +++ b/test/mp_eval_if.cpp @@ -7,9 +7,9 @@ // http://www.boost.org/LICENSE_1_0.txt -#include #include #include +#include #include int main() diff --git a/test/mp_if.cpp b/test/mp_if.cpp index 96097f6..88036f9 100644 --- a/test/mp_if.cpp +++ b/test/mp_if.cpp @@ -7,9 +7,9 @@ // http://www.boost.org/LICENSE_1_0.txt -#include #include #include +#include #include int main() diff --git a/test/mp_valid.cpp b/test/mp_valid.cpp new file mode 100644 index 0000000..228d42e --- /dev/null +++ b/test/mp_valid.cpp @@ -0,0 +1,72 @@ + +// Copyright 2015 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 + +template struct Xi +{ +}; + +template<> struct Xi +{ + using type = void; +}; + +template using X = typename Xi::type; + +template using add_pointer = T*; +template using add_reference = T&; +template using add_extents = T[]; + +int main() +{ + using boost::mp_valid; + using boost::mp_identity; + + BOOST_TEST_TRAIT_FALSE((mp_valid)); + BOOST_TEST_TRAIT_TRUE((mp_valid)); + BOOST_TEST_TRAIT_FALSE((mp_valid)); + + BOOST_TEST_TRAIT_FALSE((mp_valid)); + BOOST_TEST_TRAIT_TRUE((mp_valid)); + BOOST_TEST_TRAIT_FALSE((mp_valid)); + BOOST_TEST_TRAIT_FALSE((mp_valid)); + + BOOST_TEST_TRAIT_FALSE((mp_valid)); + BOOST_TEST_TRAIT_TRUE((mp_valid)); + BOOST_TEST_TRAIT_TRUE((mp_valid)); +#if !defined( BOOST_MSVC ) || !BOOST_WORKAROUND( BOOST_MSVC, <= 1800 ) + // msvc-12.0 can form pointer to reference + BOOST_TEST_TRAIT_FALSE((mp_valid)); +#endif + BOOST_TEST_TRAIT_FALSE((mp_valid)); + +#if !defined( BOOST_GCC ) || !BOOST_WORKAROUND( BOOST_GCC, <= 40902 ) + // g++ 4.9.2 doesn't like add_reference for some reason or other + BOOST_TEST_TRAIT_FALSE((mp_valid)); +#if !defined( BOOST_MSVC ) || !BOOST_WORKAROUND( BOOST_MSVC, <= 1800 ) + // msvc-12.0 gives an internal error here + BOOST_TEST_TRAIT_FALSE((mp_valid)); +#endif + BOOST_TEST_TRAIT_TRUE((mp_valid)); + BOOST_TEST_TRAIT_FALSE((mp_valid)); +#endif + + BOOST_TEST_TRAIT_FALSE((mp_valid)); + BOOST_TEST_TRAIT_TRUE((mp_valid)); +#if !defined( BOOST_MSVC ) || !BOOST_WORKAROUND( BOOST_MSVC, <= 1800 ) + // msvc-12.0 can form arrays to void or int& + BOOST_TEST_TRAIT_FALSE((mp_valid)); + BOOST_TEST_TRAIT_FALSE((mp_valid)); +#endif + BOOST_TEST_TRAIT_FALSE((mp_valid)); + + return boost::report_errors(); +}