brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.8 KiB · 560ae8b Raw
424 lines · plain
1//  Copyright Peter Dimov 2015-2021.2//  Copyright Matt Borland 2021.3//  Use, modification and distribution are subject to the4//  Boost Software License, Version 1.0. (See accompanying file5//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)6//7//  Template metaprogramming classes and functions to replace MPL8//  Source: http://www.pdimov.com/cpp2/simple_cxx11_metaprogramming.html9//  Source: https://github.com/boostorg/mp11/10 11#ifndef BOOST_MATH_TOOLS_MP12#define BOOST_MATH_TOOLS_MP13 14#include <boost/math/tools/config.hpp>15#include <boost/math/tools/type_traits.hpp>16#include <boost/math/tools/cstdint.hpp>17 18namespace boost { namespace math { namespace tools { namespace meta_programming {19 20// Types:21// Typelist 22template<typename... T>23struct mp_list {};24 25// Size_t26template<boost::math::size_t N> 27using mp_size_t = boost::math::integral_constant<boost::math::size_t, N>;28 29// Boolean30template<bool B>31using mp_bool = boost::math::integral_constant<bool, B>;32 33// Identity34template<typename T>35struct mp_identity36{37    using type = T;38};39 40// Turns struct into quoted metafunction41template<template<typename...> class F> 42struct mp_quote_trait43{44    template<typename... T> 45    using fn = typename F<T...>::type;46};47 48namespace detail {49// Size50template<typename L> 51struct mp_size_impl {};52 53template<template<typename...> class L, typename... T> // Template template parameter must use class54struct mp_size_impl<L<T...>>55{56    using type = boost::math::integral_constant<boost::math::size_t, sizeof...(T)>;57};58}59 60template<typename T> 61using mp_size = typename detail::mp_size_impl<T>::type;62 63namespace detail {64// Front65template<typename L>66struct mp_front_impl {};67 68template<template<typename...> class L, typename T1, typename... T> 69struct mp_front_impl<L<T1, T...>>70{71    using type = T1;72};73}74 75template<typename T>76using mp_front = typename detail::mp_front_impl<T>::type;77 78namespace detail {79// At80// TODO - Use tree based lookup for larger typelists81// http://odinthenerd.blogspot.com/2017/04/tree-based-lookup-why-kvasirmpl-is.html82template<typename L, boost::math::size_t>83struct mp_at_c {};84 85template<template<typename...> class L, typename T0, typename... T>86struct mp_at_c<L<T0, T...>, 0>87{88    using type = T0;89};90 91template<template<typename...> class L, typename T0, typename T1, typename... T>92struct mp_at_c<L<T0, T1, T...>, 1>93{94    using type = T1;95};96 97template<template<typename...> class L, typename T0, typename T1, typename T2, typename... T>98struct mp_at_c<L<T0, T1, T2, T...>, 2>99{100    using type = T2;101};102 103template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename... T>104struct mp_at_c<L<T0, T1, T2, T3, T...>, 3>105{106    using type = T3;107};108 109template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename... T>110struct mp_at_c<L<T0, T1, T2, T3, T4, T...>, 4>111{112    using type = T4;113};114 115template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename... T>116struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T...>, 5>117{118    using type = T5;119};120 121template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,122         typename... T>123struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T...>, 6>124{125    using type = T6;126};127 128template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,129         typename T7, typename... T>130struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T...>, 7>131{132    using type = T7;133};134 135template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,136         typename T7, typename T8, typename... T>137struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T...>, 8>138{139    using type = T8;140};141 142template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,143         typename T7, typename T8, typename T9, typename... T>144struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>, 9>145{146    using type = T9;147};148 149template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,150         typename T7, typename T8, typename T9, typename T10, typename... T>151struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, 10>152{153    using type = T10;154};155 156template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,157         typename T7, typename T8, typename T9, typename T10, typename T11, typename... T>158struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T...>, 11>159{160    using type = T11;161};162 163template<template<typename...> class L, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6,164         typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename... T>165struct mp_at_c<L<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T...>, 12>166{167    using type = T12;168};169}170 171template<typename L, boost::math::size_t Index>172using mp_at_c = typename detail::mp_at_c<L, Index>::type;173 174template<typename L, typename Index>175using mp_at = typename detail::mp_at_c<L, Index::value>::type;176 177// Back178template<typename L> 179using mp_back = mp_at_c<L, mp_size<L>::value - 1>;180 181namespace detail {182// Push back183template<typename L, typename... T> 184struct mp_push_back_impl {};185 186template<template<typename...> class L, typename... U, typename... T> 187struct mp_push_back_impl<L<U...>, T...>188{189    using type = L<U..., T...>;190};191}192 193template<typename L, typename... T>194using mp_push_back = typename detail::mp_push_back_impl<L, T...>::type;195 196namespace detail {197// Push front198template<typename L, typename... T>199struct mp_push_front_impl {};200 201template<template<typename...> class L, typename... U, typename... T>202struct mp_push_front_impl<L<U...>, T...>203{204    using type = L<T..., U...>;205};206}207 208template<typename L, typename... T> 209using mp_push_front = typename detail::mp_push_front_impl<L, T...>::type;210 211namespace detail{212// If213template<bool C, typename T, typename... E>214struct mp_if_c_impl{};215 216template<typename T, typename... E>217struct mp_if_c_impl<true, T, E...>218{219    using type = T;220};221 222template<typename T, typename E>223struct mp_if_c_impl<false, T, E>224{225    using type = E;226};227}228 229template<bool C, typename T, typename... E> 230using mp_if_c = typename detail::mp_if_c_impl<C, T, E...>::type;231 232template<typename C, typename T, typename... E> 233using mp_if = typename detail::mp_if_c_impl<static_cast<bool>(C::value), T, E...>::type;234 235namespace detail {236// Find if237template<typename L, template<typename...> class P>238struct mp_find_if_impl {};239 240template<template<typename...> class L, template<typename...> class P> 241struct mp_find_if_impl<L<>, P>242{243    using type = mp_size_t<0>;244};245 246template<typename L, template<typename...> class P> 247struct mp_find_if_impl_2248{249    using r = typename mp_find_if_impl<L, P>::type;250    using type = mp_size_t<1 + r::value>;251};252 253template<template<typename...> class L, typename T1, typename... T, template<typename...> class P> 254struct mp_find_if_impl<L<T1, T...>, P>255{256    using type = typename mp_if<P<T1>, mp_identity<mp_size_t<0>>, mp_find_if_impl_2<mp_list<T...>, P>>::type;257};258}259 260template<typename L, template<typename...> class P> 261using mp_find_if = typename detail::mp_find_if_impl<L, P>::type;262 263template<typename L, typename Q> 264using mp_find_if_q = mp_find_if<L, Q::template fn>;265 266namespace detail {267// Append268template<typename... L> 269struct mp_append_impl {};270 271template<> 272struct mp_append_impl<>273{274    using type = mp_list<>;275};276 277template<template<typename...> class L, typename... T>278struct mp_append_impl<L<T...>>279{280    using type = L<T...>;281};282 283template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2>284struct mp_append_impl<L1<T1...>, L2<T2...>>285{286    using type = L1<T1..., T2...>;287};288 289template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2, 290         template<typename...> class L3, typename... T3>291struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>>292{293    using type = L1<T1..., T2..., T3...>;294};295 296template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2, 297         template<typename...> class L3, typename... T3, template<typename...> class L4, typename... T4>298struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>>299{300    using type = L1<T1..., T2..., T3..., T4...>;301};302 303template<template<typename...> class L1, typename... T1, template<typename...> class L2, typename... T2,304         template<typename...> class L3, typename... T3, template<typename...> class L4, typename... T4, 305         template<typename...> class L5, typename... T5, typename... Lr> 306struct mp_append_impl<L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>, L5<T5...>, Lr...>307{308    using type = typename mp_append_impl<L1<T1..., T2..., T3..., T4..., T5...>, Lr...>::type;309};310}311 312template<typename... L> 313using mp_append = typename detail::mp_append_impl<L...>::type;314 315namespace detail {316// Remove if317template<typename L, template<typename...> class P> 318struct mp_remove_if_impl{};319 320template<template<typename...> class L, typename... T, template<typename...> class P>321struct mp_remove_if_impl<L<T...>, P>322{    323    template<typename U> 324    struct _f 325    { 326        using type = mp_if<P<U>, mp_list<>, mp_list<U>>; 327    };328    329    using type = mp_append<L<>, typename _f<T>::type...>;330};331}332 333template<typename L, template<class...> class P> 334using mp_remove_if = typename detail::mp_remove_if_impl<L, P>::type;335 336template<typename L, typename Q> 337using mp_remove_if_q = mp_remove_if<L, Q::template fn>;338 339template<typename T, T... Index>340struct integer_sequence {};341 342template<boost::math::size_t... Index>343using index_sequence = integer_sequence<boost::math::size_t, Index...>;344 345namespace detail {346 347template<bool C, typename T, typename E>348struct iseq_if_c_impl {};349 350template<typename T, typename F>351struct iseq_if_c_impl<true, T, F>352{353    using type = T;354};355 356template<typename T, typename F>357struct iseq_if_c_impl<false, T, F>358{359    using type = F;360};361 362template<bool C, typename T, typename F>363using iseq_if_c = typename iseq_if_c_impl<C, T, F>::type;364 365template<typename T>366struct iseq_identity367{368    using type = T;369};370 371template<typename T1, typename T2>372struct append_integer_sequence {};373 374template<typename T, T... Index, T... J>375struct append_integer_sequence<integer_sequence<T, Index...>, integer_sequence<T, J...>>376{377    using type = integer_sequence<T, Index..., (J + sizeof...(Index))...>;378};379 380template<typename T, T N>381struct make_integer_sequence_impl;382 383template<typename T, T N>384class make_integer_sequence_impl_385{386private:387    static_assert(N >= 0, "N must not be negative");388 389    static constexpr T M = N / 2;390    static constexpr T R = N % 2;391 392    using seq1 = typename make_integer_sequence_impl<T, M>::type;393    using seq2 = typename append_integer_sequence<seq1, seq1>::type;394    using seq3 = typename make_integer_sequence_impl<T, R>::type;395    using seq4 = typename append_integer_sequence<seq2, seq3>::type;396 397public:398    using type = seq4;399};400 401template<typename T, T N>402struct make_integer_sequence_impl403{404    using type = typename iseq_if_c<N == 0, 405                                    iseq_identity<integer_sequence<T>>, 406                                    iseq_if_c<N == 1, iseq_identity<integer_sequence<T, 0>>, 407                                    make_integer_sequence_impl_<T, N>>>::type;408};409 410} // namespace detail411 412template<typename T, T N>413using make_integer_sequence = typename detail::make_integer_sequence_impl<T, N>::type;414 415template<boost::math::size_t N>416using make_index_sequence = make_integer_sequence<boost::math::size_t, N>;417 418template<typename... T>419using index_sequence_for = make_integer_sequence<boost::math::size_t, sizeof...(T)>;420 421}}}} // namespaces422 423#endif // BOOST_MATH_TOOLS_MP424