Update mp_fold to be SFINAE-friendly (for up to 9 elements)

This commit is contained in:
Peter Dimov
2023-03-24 05:13:48 +02:00
parent b937a27f7e
commit f16707f6e9
5 changed files with 277 additions and 99 deletions
+119
View File
@@ -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 <boost/mp11/integral.hpp>
#include <boost/mp11/detail/config.hpp>
namespace boost
{
namespace mp11
{
// mp_if, mp_if_c
namespace detail
{
template<bool C, class T, class... E> struct mp_if_c_impl
{
};
template<class T, class... E> struct mp_if_c_impl<true, T, E...>
{
using type = T;
};
template<class T, class E> struct mp_if_c_impl<false, T, E>
{
using type = E;
};
} // namespace detail
template<bool C, class T, class... E> using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type;
template<class C, class T, class... E> using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(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<class...> using void_t = void;
template<class, template<class...> class F, class... T>
struct mp_valid_impl: mp_false {};
template<template<class...> class F, class... T>
struct mp_valid_impl<void_t<F<T...>>, F, T...>: mp_true {};
} // namespace detail
template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<void, F, T...>;
#else
// implementation by Bruno Dutra (by the name is_evaluable)
namespace detail
{
template<template<class...> class F, class... T> struct mp_valid_impl
{
template<template<class...> class G, class = G<T...>> static mp_true check(int);
template<template<class...> class> static mp_false check(...);
using type = decltype(check<F>(0));
};
} // namespace detail
template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<F, T...>::type;
#endif
template<class Q, class... T> using mp_valid_q = mp_valid<Q::template fn, T...>;
// mp_defer
namespace detail
{
template<template<class...> class F, class... T> struct mp_defer_impl
{
using type = F<T...>;
};
struct mp_no_type
{
};
#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
template<template<class...> class F, class... T> struct mp_defer_cuda_workaround
{
using type = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;
};
#endif
} // namespace detail
#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
template<template<class...> class F, class... T> using mp_defer = typename detail::mp_defer_cuda_workaround< F, T...>::type;
#else
template<template<class...> class F, class... T> using mp_defer = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;
#endif
} // namespace mp11
} // namespace boost
#endif // #ifndef BOOST_MP11_DETAIL_MP_DEFER_HPP_INCLUDED
+105 -3
View File
@@ -9,6 +9,7 @@
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/mp11/detail/config.hpp>
#include <boost/mp11/detail/mp_defer.hpp>
namespace boost
{
@@ -41,12 +42,113 @@ template<template<class...> class L, class V, template<class...> class F> struct
#endif
template<template<class...> class L, class T1, class... T, class V, template<class...> class F> struct mp_fold_impl<L<T1, T...>, V, F>
//
template<class V, template<class...> class F> struct mp_fold_Q1
{
using type = typename mp_fold_impl<L<T...>, F<V, T1>, F>::type;
template<class T1>
using fn = F<V, T1>;
};
template<template<class...> 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...> class F> struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, V, F>
template<class V, template<class...> class F> struct mp_fold_Q2
{
template<class T1, class T2>
using fn = F<F<V, T1>, T2>;
};
template<class V, template<class...> class F> struct mp_fold_Q3
{
template<class T1, class T2, class T3>
using fn = F<F<F<V, T1>, T2>, T3>;
};
template<class V, template<class...> class F> struct mp_fold_Q4
{
template<class T1, class T2, class T3, class T4>
using fn = F<F<F<F<V, T1>, T2>, T3>, T4>;
};
template<class V, template<class...> class F> struct mp_fold_Q5
{
template<class T1, class T2, class T3, class T4, class T5>
using fn = F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>;
};
template<class V, template<class...> class F> struct mp_fold_Q6
{
template<class T1, class T2, class T3, class T4, class T5, class T6>
using fn = F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>;
};
template<class V, template<class...> class F> struct mp_fold_Q7
{
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7>
using fn = F<F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>, T7>;
};
template<class V, template<class...> class F> struct mp_fold_Q8
{
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
using fn = F<F<F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>, T7>, T8>;
};
template<class V, template<class...> class F> struct mp_fold_Q9
{
template<class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
using fn = F<F<F<F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>;
};
//
template<template<class...> class L, class T1, class V, template<class...> class F>
struct mp_fold_impl<L<T1>, V, F>: mp_defer<mp_fold_Q1<V, F>::template fn, T1>
{
};
template<template<class...> class L, class T1, class T2, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2>, V, F>: mp_defer<mp_fold_Q2<V, F>::template fn, T1, T2>
{
};
template<template<class...> class L, class T1, class T2, class T3, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3>, V, F>: mp_defer<mp_fold_Q3<V, F>::template fn, T1, T2, T3>
{
};
template<template<class...> class L, class T1, class T2, class T3, class T4, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3, T4>, V, F>: mp_defer<mp_fold_Q4<V, F>::template fn, T1, T2, T3, T4>
{
};
template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3, T4, T5>, V, F>: mp_defer<mp_fold_Q5<V, F>::template fn, T1, T2, T3, T4, T5>
{
};
template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6>, V, F>: mp_defer<mp_fold_Q6<V, F>::template fn, T1, T2, T3, T4, T5, T6>
{
};
template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6, T7>, V, F>: mp_defer<mp_fold_Q7<V, F>::template fn, T1, T2, T3, T4, T5, T6, T7>
{
};
template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6, T7, T8>, V, F>: mp_defer<mp_fold_Q8<V, F>::template fn, T1, T2, T3, T4, T5, T6, T7, T8>
{
};
template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class V, template<class...> class F>
struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6, T7, T8, T9>, V, F>: mp_defer<mp_fold_Q9<V, F>::template fn, T1, T2, T3, T4, T5, T6, T7, T8, T9>
{
};
//
template<template<class...> 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...> class F>
struct mp_fold_impl<L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, V, F>
{
using type = typename mp_fold_impl<L<T...>, F<F<F<F<F<F<F<F<F<F<V, T1>, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>, T10>, F>::type;
};
+2 -96
View File
@@ -13,6 +13,7 @@
#include <boost/mp11/detail/mp_fold.hpp>
#include <boost/mp11/detail/mp_front.hpp>
#include <boost/mp11/detail/mp_rename.hpp>
#include <boost/mp11/detail/mp_defer.hpp>
#include <boost/mp11/detail/config.hpp>
namespace boost
@@ -33,104 +34,9 @@ template<class T> using mp_identity_t = typename mp_identity<T>::type;
template<class... T> struct mp_inherit: T... {};
// mp_if, mp_if_c
namespace detail
{
template<bool C, class T, class... E> struct mp_if_c_impl
{
};
template<class T, class... E> struct mp_if_c_impl<true, T, E...>
{
using type = T;
};
template<class T, class E> struct mp_if_c_impl<false, T, E>
{
using type = E;
};
} // namespace detail
template<bool C, class T, class... E> using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type;
template<class C, class T, class... E> using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(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<class...> using void_t = void;
template<class, template<class...> class F, class... T>
struct mp_valid_impl: mp_false {};
template<template<class...> class F, class... T>
struct mp_valid_impl<void_t<F<T...>>, F, T...>: mp_true {};
} // namespace detail
template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<void, F, T...>;
#else
// implementation by Bruno Dutra (by the name is_evaluable)
namespace detail
{
template<template<class...> class F, class... T> struct mp_valid_impl
{
template<template<class...> class G, class = G<T...>> static mp_true check(int);
template<template<class...> class> static mp_false check(...);
using type = decltype(check<F>(0));
};
} // namespace detail
template<template<class...> class F, class... T> using mp_valid = typename detail::mp_valid_impl<F, T...>::type;
#endif
template<class Q, class... T> using mp_valid_q = mp_valid<Q::template fn, T...>;
// mp_defer
namespace detail
{
template<template<class...> class F, class... T> struct mp_defer_impl
{
using type = F<T...>;
};
struct mp_no_type
{
};
#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
template<template<class...> class F, class... T> struct mp_defer_cuda_workaround
{
using type = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;
};
#endif
} // namespace detail
#if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
template<template<class...> class F, class... T> using mp_defer = typename detail::mp_defer_cuda_workaround< F, T...>::type;
#else
template<template<class...> class F, class... T> using mp_defer = mp_if<mp_valid<F, T...>, detail::mp_defer_impl<F, T...>, detail::mp_no_type>;
#endif
// moved to detail/mp_defer.hpp
// mp_eval_if, mp_eval_if_c
namespace detail