From 61b897e8572e0ce0d15b17e1fea0e6cc516d3e40 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 16 Jul 2015 00:40:40 +0300 Subject: [PATCH] Add mp_valid, mp_defer, mp_defer_if_valid. --- include/boost/mp11/utility.hpp | 24 ++++++++++++ test/Jamfile.v2 | 3 ++ test/mp_defer.cpp | 26 ++++++++++++ test/mp_defer_if_valid.cpp | 29 ++++++++++++++ test/mp_valid.cpp | 72 ++++++++++++++++++++++++++++++++++ 5 files changed, 154 insertions(+) create mode 100644 test/mp_defer.cpp create mode 100644 test/mp_defer_if_valid.cpp create mode 100644 test/mp_valid.cpp diff --git a/include/boost/mp11/utility.hpp b/include/boost/mp11/utility.hpp index b41d334..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 { @@ -63,8 +65,30 @@ template class F, class... U> using mp_eval_ 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/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_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(); +}