diff --git a/include/boost/mp11/detail/mp_defer.hpp b/include/boost/mp11/detail/mp_defer.hpp new file mode 100644 index 0000000..9aaca99 --- /dev/null +++ b/include/boost/mp11/detail/mp_defer.hpp @@ -0,0 +1,119 @@ +#ifndef BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED +#define BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED + +// Copyright 2015-2020, 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include + +namespace boost +{ +namespace mp11 +{ + +// mp_if, mp_if_c +namespace detail +{ + +template struct mp_if_c_impl +{ +}; + +template struct mp_if_c_impl +{ + using type = T; +}; + +template struct mp_if_c_impl +{ + using type = E; +}; + +} // namespace detail + +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_valid + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_INTEL, != 0 ) // tested at 1800 + +// contributed by Roland Schulz in https://github.com/boostorg/mp11/issues/17 + +namespace detail +{ + +template using void_t = void; + +template class F, class... T> +struct mp_valid_impl: mp_false {}; + +template class F, class... T> +struct mp_valid_impl>, F, T...>: mp_true {}; + +} // namespace detail + +template class F, class... T> using mp_valid = typename detail::mp_valid_impl; + +#else + +// 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; + +#endif + +template using mp_valid_q = mp_valid; + +// mp_defer +namespace detail +{ + +template class F, class... T> struct mp_defer_impl +{ + using type = F; +}; + +struct mp_no_type +{ +}; + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) + +template class F, class... T> struct mp_defer_cuda_workaround +{ + using type = mp_if, detail::mp_defer_impl, detail::mp_no_type>; +}; + +#endif + +} // namespace detail + +#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) + +template class F, class... T> using mp_defer = typename detail::mp_defer_cuda_workaround< F, T...>::type; + +#else + +template class F, class... T> using mp_defer = mp_if, detail::mp_defer_impl, detail::mp_no_type>; + +#endif + +} // namespace mp11 +} // namespace boost + +#endif // #ifndef BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED diff --git a/include/boost/mp11/detail/mp_fold.hpp b/include/boost/mp11/detail/mp_fold.hpp index 0745e87..266d9c1 100644 --- a/include/boost/mp11/detail/mp_fold.hpp +++ b/include/boost/mp11/detail/mp_fold.hpp @@ -9,6 +9,7 @@ // http://www.boost.org/LICENSE_1_0.txt #include +#include namespace boost { @@ -41,12 +42,113 @@ template class L, class V, template class F> struct #endif -template class L, class T1, class... T, class V, template class F> struct mp_fold_impl, V, F> +// + +template class F> struct mp_fold_Q1 { - using type = typename mp_fold_impl, F, F>::type; + template + using fn = F; }; -template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T, class V, template class F> struct mp_fold_impl, V, F> +template class F> struct mp_fold_Q2 +{ + template + using fn = F, T2>; +}; + +template class F> struct mp_fold_Q3 +{ + template + using fn = F, T2>, T3>; +}; + +template class F> struct mp_fold_Q4 +{ + template + using fn = F, T2>, T3>, T4>; +}; + +template class F> struct mp_fold_Q5 +{ + template + using fn = F, T2>, T3>, T4>, T5>; +}; + +template class F> struct mp_fold_Q6 +{ + template + using fn = F, T2>, T3>, T4>, T5>, T6>; +}; + +template class F> struct mp_fold_Q7 +{ + template + using fn = F, T2>, T3>, T4>, T5>, T6>, T7>; +}; + +template class F> struct mp_fold_Q8 +{ + template + using fn = F, T2>, T3>, T4>, T5>, T6>, T7>, T8>; +}; + +template class F> struct mp_fold_Q9 +{ + template + using fn = F, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>; +}; + +// + +template class L, class T1, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1> +{ +}; + +template class L, class T1, class T2, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2> +{ +}; + +template class L, class T1, class T2, class T3, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5, T6> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5, T6, T7> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5, T6, T7, T8> +{ +}; + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class V, template class F> +struct mp_fold_impl, V, F>: mp_defer::template fn, T1, T2, T3, T4, T5, T6, T7, T8, T9> +{ +}; + +// + +template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T, class V, template class F> +struct mp_fold_impl, V, F> { using type = typename mp_fold_impl, F, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>, T10>, F>::type; }; diff --git a/include/boost/mp11/utility.hpp b/include/boost/mp11/utility.hpp index fbab4a3..4010aee 100644 --- a/include/boost/mp11/utility.hpp +++ b/include/boost/mp11/utility.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace boost @@ -33,104 +34,9 @@ template using mp_identity_t = typename mp_identity::type; template struct mp_inherit: T... {}; // mp_if, mp_if_c -namespace detail -{ - -template struct mp_if_c_impl -{ -}; - -template struct mp_if_c_impl -{ - using type = T; -}; - -template struct mp_if_c_impl -{ - using type = E; -}; - -} // namespace detail - -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_valid - -#if BOOST_MP11_WORKAROUND( BOOST_MP11_INTEL, != 0 ) // tested at 1800 - -// contributed by Roland Schulz in https://github.com/boostorg/mp11/issues/17 - -namespace detail -{ - -template using void_t = void; - -template class F, class... T> -struct mp_valid_impl: mp_false {}; - -template class F, class... T> -struct mp_valid_impl>, F, T...>: mp_true {}; - -} // namespace detail - -template class F, class... T> using mp_valid = typename detail::mp_valid_impl; - -#else - -// 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; - -#endif - -template using mp_valid_q = mp_valid; - // mp_defer -namespace detail -{ - -template class F, class... T> struct mp_defer_impl -{ - using type = F; -}; - -struct mp_no_type -{ -}; - -#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) - -template class F, class... T> struct mp_defer_cuda_workaround -{ - using type = mp_if, detail::mp_defer_impl, detail::mp_no_type>; -}; - -#endif - -} // namespace detail - -#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) - -template class F, class... T> using mp_defer = typename detail::mp_defer_cuda_workaround< F, T...>::type; - -#else - -template class F, class... T> using mp_defer = mp_if, detail::mp_defer_impl, detail::mp_no_type>; - -#endif +// moved to detail/mp_defer.hpp // mp_eval_if, mp_eval_if_c namespace detail diff --git a/test/Jamfile b/test/Jamfile index 0e25055..28ce8e9 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -88,6 +88,7 @@ run mp_find_if_q.cpp ; run mp_reverse.cpp ; run mp_fold.cpp ; run mp_fold_q.cpp ; +run mp_fold_q_sf.cpp ; run mp_reverse_fold.cpp ; run mp_reverse_fold_q.cpp ; run mp_unique.cpp ; diff --git a/test/mp_fold_q_sf.cpp b/test/mp_fold_q_sf.cpp new file mode 100644 index 0000000..cd116ab --- /dev/null +++ b/test/mp_fold_q_sf.cpp @@ -0,0 +1,50 @@ +// Copyright 2023 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include + +using boost::mp11::mp_size_t; + +struct Q +{ + template using fn = mp_size_t; +}; + +int main() +{ + using boost::mp11::mp_valid; + using boost::mp11::mp_fold_q; + using boost::mp11::mp_list; + + BOOST_TEST_TRAIT_TRUE((mp_valid, mp_size_t<0>, Q>)); + BOOST_TEST_TRAIT_TRUE((mp_valid, mp_size_t<0>, Q>)); + BOOST_TEST_TRAIT_TRUE((mp_valid, mp_size_t<0>, Q>)); + BOOST_TEST_TRAIT_TRUE((mp_valid, mp_size_t<0>, Q>)); + BOOST_TEST_TRAIT_TRUE((mp_valid, mp_size_t<0>, Q>)); + + BOOST_TEST_TRAIT_FALSE((mp_valid, mp_size_t<0>, Q>)); + BOOST_TEST_TRAIT_FALSE((mp_valid, mp_size_t<0>, Q>)); + BOOST_TEST_TRAIT_FALSE((mp_valid, mp_size_t<0>, Q>)); + BOOST_TEST_TRAIT_FALSE((mp_valid, mp_size_t<0>, Q>)); + +#if !BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1910 ) + + BOOST_TEST_TRAIT_FALSE((mp_valid, mp_size_t<0>, Q>)); + BOOST_TEST_TRAIT_FALSE((mp_valid, mp_size_t<0>, Q>)); + BOOST_TEST_TRAIT_FALSE((mp_valid, mp_size_t<0>, Q>)); + + BOOST_TEST_TRAIT_FALSE((mp_valid, mp_size_t<0>, Q>)); + BOOST_TEST_TRAIT_FALSE((mp_valid, mp_size_t<0>, Q>)); + + BOOST_TEST_TRAIT_FALSE((mp_valid, mp_size_t<0>, Q>)); + +#endif + + return boost::report_errors(); +}