// Copyright Peter Dimov 2015-2021. // Copyright Matt Borland 2021. // Use, modification and distribution are subject to 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) // // Template metaprogramming classes and functions to replace MPL // Source: http://www.pdimov.com/cpp2/simple_cxx11_metaprogramming.html // Source: https://github.com/boostorg/mp11/ #ifndef BOOST_MATH_TOOLS_MP #define BOOST_MATH_TOOLS_MP #include #include #include namespace boost { namespace math { namespace tools { namespace meta_programming { // Types: // Typelist template struct mp_list {}; // Size_t template using mp_size_t = std::integral_constant; // Boolean template using mp_bool = std::integral_constant; // Identity template struct mp_identity { using type = T; }; // Turns struct into quoted metafunction template class F> struct mp_quote_trait { template using fn = typename F::type; }; namespace detail { // Size template struct mp_size_impl {}; template class L, typename... T> // Template template parameter must use class struct mp_size_impl> { using type = std::integral_constant; }; } template using mp_size = typename detail::mp_size_impl::type; namespace detail { // Front template struct mp_front_impl {}; template class L, typename T1, typename... T> struct mp_front_impl> { using type = T1; }; } template using mp_front = typename detail::mp_front_impl::type; namespace detail { // At // TODO - Use tree based lookup for larger typelists // http://odinthenerd.blogspot.com/2017/04/tree-based-lookup-why-kvasirmpl-is.html template struct mp_at_c {}; template class L, typename T0, typename... T> struct mp_at_c, 0> { using type = T0; }; template class L, typename T0, typename T1, typename... T> struct mp_at_c, 1> { using type = T1; }; template class L, typename T0, typename T1, typename T2, typename... T> struct mp_at_c, 2> { using type = T2; }; template class L, typename T0, typename T1, typename T2, typename T3, typename... T> struct mp_at_c, 3> { using type = T3; }; template class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename... T> struct mp_at_c, 4> { using type = T4; }; template class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename... T> struct mp_at_c, 5> { using type = T5; }; template class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename... T> struct mp_at_c, 6> { using type = T6; }; template class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename... T> struct mp_at_c, 7> { using type = T7; }; template class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename... T> struct mp_at_c, 8> { using type = T8; }; template class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename... T> struct mp_at_c, 9> { using type = T9; }; template class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename... T> struct mp_at_c, 10> { using type = T10; }; template class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename... T> struct mp_at_c, 11> { using type = T11; }; template class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename... T> struct mp_at_c, 12> { using type = T12; }; } template using mp_at_c = typename detail::mp_at_c::type; template using mp_at = typename detail::mp_at_c::type; // Back template using mp_back = mp_at_c::value - 1>; namespace detail { // Push back template struct mp_push_back_impl {}; template class L, typename... U, typename... T> struct mp_push_back_impl, T...> { using type = L; }; } template using mp_push_back = typename detail::mp_push_back_impl::type; namespace detail { // Push front template struct mp_push_front_impl {}; template class L, typename... U, typename... T> struct mp_push_front_impl, T...> { using type = L; }; } template using mp_push_front = typename detail::mp_push_front_impl::type; namespace detail{ // If template struct mp_if_c_impl{}; template struct mp_if_c_impl { using type = T; }; template struct mp_if_c_impl { using type = E; }; } 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; namespace detail { // Find if template class P> struct mp_find_if_impl {}; template class L, template class P> struct mp_find_if_impl, P> { using type = mp_size_t<0>; }; template class P> struct mp_find_if_impl_2 { using r = typename mp_find_if_impl::type; using type = mp_size_t<1 + r::value>; }; template class L, typename T1, typename... T, template class P> struct mp_find_if_impl, P> { using type = typename mp_if, mp_identity>, mp_find_if_impl_2, P>>::type; }; } template class P> using mp_find_if = typename detail::mp_find_if_impl::type; template using mp_find_if_q = mp_find_if; namespace detail { // Append template struct mp_append_impl {}; template<> struct mp_append_impl<> { using type = mp_list<>; }; template class L, typename... T> struct mp_append_impl> { using type = L; }; template class L1, typename... T1, template class L2, typename... T2> struct mp_append_impl, L2> { using type = L1; }; template class L1, typename... T1, template class L2, typename... T2, template class L3, typename... T3> struct mp_append_impl, L2, L3> { using type = L1; }; template class L1, typename... T1, template class L2, typename... T2, template class L3, typename... T3, template class L4, typename... T4> struct mp_append_impl, L2, L3, L4> { using type = L1; }; template class L1, typename... T1, template class L2, typename... T2, template class L3, typename... T3, template class L4, typename... T4, template class L5, typename... T5, typename... Lr> struct mp_append_impl, L2, L3, L4, L5, Lr...> { using type = typename mp_append_impl, Lr...>::type; }; } template using mp_append = typename detail::mp_append_impl::type; namespace detail { // Remove if template class P> struct mp_remove_if_impl{}; template class L, typename... T, template class P> struct mp_remove_if_impl, P> { template struct _f { using type = mp_if, mp_list<>, mp_list>; }; using type = mp_append, typename _f::type...>; }; } template class P> using mp_remove_if = typename detail::mp_remove_if_impl::type; template using mp_remove_if_q = mp_remove_if; // Index sequence // Use C++14 index sequence if available #if defined(__cpp_lib_integer_sequence) && (__cpp_lib_integer_sequence >= 201304) template using index_sequence = std::index_sequence; template using make_index_sequence = std::make_index_sequence; template using index_sequence_for = std::index_sequence_for; #else template struct integer_sequence {}; template using index_sequence = integer_sequence; namespace detail { template struct iseq_if_c_impl {}; template struct iseq_if_c_impl { using type = T; }; template struct iseq_if_c_impl { using type = F; }; template using iseq_if_c = typename iseq_if_c_impl::type; template struct iseq_identity { using type = T; }; template struct append_integer_sequence {}; template struct append_integer_sequence, integer_sequence> { using type = integer_sequence; }; template struct make_integer_sequence_impl; template class make_integer_sequence_impl_ { private: static_assert(N >= 0, "N must not be negative"); static constexpr T M = N / 2; static constexpr T R = N % 2; using seq1 = typename make_integer_sequence_impl::type; using seq2 = typename append_integer_sequence::type; using seq3 = typename make_integer_sequence_impl::type; using seq4 = typename append_integer_sequence::type; public: using type = seq4; }; template struct make_integer_sequence_impl { using type = typename iseq_if_c>, iseq_if_c>, make_integer_sequence_impl_>>::type; }; } // namespace detail template using make_integer_sequence = typename detail::make_integer_sequence_impl::type; template using make_index_sequence = make_integer_sequence; template using index_sequence_for = make_integer_sequence; #endif }}}} // namespaces #endif // BOOST_MATH_TOOLS_MP