123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- // 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 <type_traits>
- #include <cstddef>
- namespace boost { namespace math { namespace tools { namespace meta_programming {
- // Types:
- // Typelist
- template<typename... T>
- struct mp_list {};
- // Size_t
- template<std::size_t N>
- using mp_size_t = std::integral_constant<std::size_t, N>;
- // Boolean
- template<bool B>
- using mp_bool = std::integral_constant<bool, B>;
- // Identity
- template<typename T>
- struct mp_identity
- {
- using type = T;
- };
- // Turns struct into quoted metafunction
- template<template<typename...> class F>
- struct mp_quote_trait
- {
- template<typename... T>
- using fn = typename F<T...>::type;
- };
- namespace detail {
- // Size
- template<typename L>
- struct mp_size_impl {};
- template<template<typename...> class L, typename... T> // Template template parameter must use class
- struct mp_size_impl<L<T...>>
- {
- using type = std::integral_constant<std::size_t, sizeof...(T)>;
- };
- }
- template<typename T>
- using mp_size = typename detail::mp_size_impl<T>::type;
- namespace detail {
- // Front
- template<typename L>
- struct mp_front_impl {};
- template<template<typename...> class L, typename T1, typename... T>
- struct mp_front_impl<L<T1, T...>>
- {
- using type = T1;
- };
- }
- template<typename T>
- using mp_front = typename detail::mp_front_impl<T>::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<typename L, std::size_t>
- struct mp_at_c {};
- template<template<typename...> class L, typename T0, typename... T>
- struct mp_at_c<L<T0, T...>, 0>
- {
- using type = T0;
- };
- template<template<typename...> class L, typename T0, typename T1, typename... T>
- struct mp_at_c<L<T0, T1, T...>, 1>
- {
- using type = T1;
- };
- template<template<typename...> class L, typename T0, typename T1, typename T2, typename... T>
- struct mp_at_c<L<T0, T1, T2, T...>, 2>
- {
- using type = T2;
- };
- template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename... T>
- struct mp_at_c<L<T0, T1, T2, T3, T...>, 3>
- {
- using type = T3;
- };
- template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename... T>
- struct mp_at_c<L<T0, T1, T2, T3, T4, T...>, 4>
- {
- using type = T4;
- };
- template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename... T>
- struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T...>, 5>
- {
- using type = T5;
- };
- template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
- typename... T>
- struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T...>, 6>
- {
- using type = T6;
- };
- template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,
- typename T7, typename... T>
- struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T...>, 7>
- {
- using type = T7;
- };
- template<template<typename...> 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<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T...>, 8>
- {
- using type = T8;
- };
- template<template<typename...> 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<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>, 9>
- {
- using type = T9;
- };
- template<template<typename...> 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<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, 10>
- {
- using type = T10;
- };
- template<template<typename...> 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<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T...>, 11>
- {
- using type = T11;
- };
- template<template<typename...> 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<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T...>, 12>
- {
- using type = T12;
- };
- }
- template<typename L, std::size_t I>
- using mp_at_c = typename detail::mp_at_c<L, I>::type;
- template<typename L, typename I>
- using mp_at = typename detail::mp_at_c<L, I::value>::type;
- // Back
- template<typename L>
- using mp_back = mp_at_c<L, mp_size<L>::value - 1>;
- namespace detail {
- // Push back
- template<typename L, typename... T>
- struct mp_push_back_impl {};
- template<template<typename...> class L, typename... U, typename... T>
- struct mp_push_back_impl<L<U...>, T...>
- {
- using type = L<U..., T...>;
- };
- }
- template<typename L, typename... T>
- using mp_push_back = typename detail::mp_push_back_impl<L, T...>::type;
- namespace detail {
- // Push front
- template<typename L, typename... T>
- struct mp_push_front_impl {};
- template<template<typename...> class L, typename... U, typename... T>
- struct mp_push_front_impl<L<U...>, T...>
- {
- using type = L<T..., U...>;
- };
- }
- template<typename L, typename... T>
- using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type;
- namespace detail{
- // If
- template<bool C, typename T, typename... E>
- struct mp_if_c_impl{};
- template<typename T, typename... E>
- struct mp_if_c_impl<true, T, E...>
- {
- using type = T;
- };
- template<typename T, typename E>
- struct mp_if_c_impl<false, T, E>
- {
- using type = E;
- };
- }
- template<bool C, typename T, typename... E>
- using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type;
- template<typename C, typename T, typename... E>
- using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type;
- namespace detail {
- // Find if
- template<typename L, template<typename...> class P>
- struct mp_find_if_impl {};
- template<template<typename...> class L, template<typename...> class P>
- struct mp_find_if_impl<L<>, P>
- {
- using type = mp_size_t<0>;
- };
- template<typename L, template<typename...> class P>
- struct mp_find_if_impl_2
- {
- using r = typename mp_find_if_impl<L, P>::type;
- using type = mp_size_t<1 + r::value>;
- };
- template<template<typename...> class L, typename T1, typename... T, template<typename...> class P>
- struct mp_find_if_impl<L<T1, T...>, P>
- {
- using type = typename mp_if<P<T1>, mp_identity<mp_size_t<0>>, mp_find_if_impl_2<mp_list<T...>, P>>::type;
- };
- }
- template<typename L, template<typename...> class P>
- using mp_find_if = typename detail::mp_find_if_impl<L, P>::type;
- template<typename L, typename Q>
- using mp_find_if_q = mp_find_if<L, Q::template fn>;
- namespace detail {
- // Append
- template<typename... L>
- struct mp_append_impl {};
- template<>
- struct mp_append_impl<>
- {
- using type = mp_list<>;
- };
- template<template<typename...> class L, typename... T>
- struct mp_append_impl<L<T...>>
- {
- using type = L<T...>;
- };
- template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2>
- struct mp_append_impl<L1<T1...>, L2<T2...>>
- {
- using type = L1<T1..., T2...>;
- };
- template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
- template<typename...> class L3, typename... T3>
- struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>>
- {
- using type = L1<T1..., T2..., T3...>;
- };
- template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
- template<typename...> class L3, typename... T3, template<typename...> class L4, typename... T4>
- struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>>
- {
- using type = L1<T1..., T2..., T3..., T4...>;
- };
- template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,
- template<typename...> class L3, typename... T3, template<typename...> class L4, typename... T4,
- template<typename...> class L5, typename... T5, typename... Lr>
- struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>, L5<T5...>, Lr...>
- {
- using type = typename mp_append_impl<L1<T1..., T2..., T3..., T4..., T5...>, Lr...>::type;
- };
- }
- template<typename... L>
- using mp_append = typename detail::mp_append_impl<L...>::type;
- namespace detail {
- // Remove if
- template<typename L, template<typename...> class P>
- struct mp_remove_if_impl{};
- template<template<typename...> class L, typename... T, template<typename...> class P>
- struct mp_remove_if_impl<L<T...>, P>
- {
- template<typename U>
- struct _f
- {
- using type = mp_if<P<U>, mp_list<>, mp_list<U>>;
- };
-
- using type = mp_append<L<>, typename _f<T>::type...>;
- };
- }
- template<typename L, template<class...> class P>
- using mp_remove_if = typename detail::mp_remove_if_impl<L, P>::type;
- template<typename L, typename Q>
- using mp_remove_if_q = mp_remove_if<L, Q::template fn>;
- // Index sequence
- // Use C++14 index sequence if available
- #if defined(__cpp_lib_integer_sequence) && (__cpp_lib_integer_sequence >= 201304)
- #include <utility>
- template<std::size_t... I>
- using index_sequence = std::index_sequence<I...>;
- template<std::size_t N>
- using make_index_sequence = std::make_index_sequence<N>;
- template<typename... T>
- using index_sequence_for = std::index_sequence_for<T...>;
- #else
- template<typename T, T... I>
- struct integer_sequence {};
- template<std::size_t... I>
- using index_sequence = integer_sequence<std::size_t, I...>;
- namespace detail {
- template<bool C, typename T, typename E>
- struct iseq_if_c_impl {};
- template<typename T, typename F>
- struct iseq_if_c_impl<true, T, F>
- {
- using type = T;
- };
- template<typename T, typename F>
- struct iseq_if_c_impl<false, T, F>
- {
- using type = F;
- };
- template<bool C, typename T, typename F>
- using iseq_if_c = typename iseq_if_c_impl<C, T, F>::type;
- template<typename T>
- struct iseq_identity
- {
- using type = T;
- };
- template<typename T1, typename T2>
- struct append_integer_sequence {};
- template<typename T, T... I, T... J>
- struct append_integer_sequence<integer_sequence<T, I...>, integer_sequence<T, J...>>
- {
- using type = integer_sequence<T, I..., (J + sizeof...(I))...>;
- };
- template<typename T, T N>
- struct make_integer_sequence_impl;
- template<typename T, T N>
- 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<T, M>::type;
- using seq2 = typename append_integer_sequence<seq1, seq1>::type;
- using seq3 = typename make_integer_sequence_impl<T, R>::type;
- using seq4 = typename append_integer_sequence<seq2, seq3>::type;
- public:
- using type = seq4;
- };
- template<typename T, T N>
- struct make_integer_sequence_impl
- {
- using type = typename iseq_if_c<N == 0,
- iseq_identity<integer_sequence<T>>,
- iseq_if_c<N == 1, iseq_identity<integer_sequence<T, 0>>,
- make_integer_sequence_impl_<T, N>>>::type;
- };
- } // namespace detail
- template<typename T, T N>
- using make_integer_sequence = typename detail::make_integer_sequence_impl<T, N>::type;
- template<std::size_t... I>
- using index_sequence = integer_sequence<std::size_t, I...>;
- template<std::size_t N>
- using make_index_sequence = make_integer_sequence<std::size_t, N>;
- template<typename... T>
- using index_sequence_for = make_integer_sequence<std::size_t, sizeof...(T)>;
- #endif
- }}}} // namespaces
- #endif // BOOST_MATH_TOOLS_MP
|