File indexing completed on 2025-01-30 09:46:52
0001 #ifndef BOOST_MP11_ALGORITHM_HPP_INCLUDED
0002 #define BOOST_MP11_ALGORITHM_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <boost/mp11/list.hpp>
0012 #include <boost/mp11/set.hpp>
0013 #include <boost/mp11/integral.hpp>
0014 #include <boost/mp11/utility.hpp>
0015 #include <boost/mp11/function.hpp>
0016 #include <boost/mp11/detail/mp_count.hpp>
0017 #include <boost/mp11/detail/mp_plus.hpp>
0018 #include <boost/mp11/detail/mp_map_find.hpp>
0019 #include <boost/mp11/detail/mp_with_index.hpp>
0020 #include <boost/mp11/detail/mp_fold.hpp>
0021 #include <boost/mp11/detail/mp_min_element.hpp>
0022 #include <boost/mp11/detail/mp_copy_if.hpp>
0023 #include <boost/mp11/detail/mp_remove_if.hpp>
0024 #include <boost/mp11/detail/config.hpp>
0025 #include <boost/mp11/integer_sequence.hpp>
0026 #include <type_traits>
0027 #include <utility>
0028
0029 namespace boost
0030 {
0031 namespace mp11
0032 {
0033
0034
0035 namespace detail
0036 {
0037
0038 template<template<class...> class F, class... L> struct mp_transform_impl
0039 {
0040 };
0041
0042 template<template<class...> class F, template<class...> class L, class... T> struct mp_transform_impl<F, L<T...>>
0043 {
0044 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
0045
0046 template<class... U> struct f { using type = F<U...>; };
0047
0048 using type = L<typename f<T>::type...>;
0049
0050 #else
0051
0052 using type = L<F<T>...>;
0053
0054 #endif
0055 };
0056
0057 template<template<class...> class F, template<class...> class L1, class... T1, template<class...> class L2, class... T2> struct mp_transform_impl<F, L1<T1...>, L2<T2...>>
0058 {
0059 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
0060
0061 template<class... U> struct f { using type = F<U...>; };
0062
0063 using type = L1<typename f<T1, T2>::type...>;
0064
0065 #else
0066
0067 using type = L1<F<T1,T2>...>;
0068
0069 #endif
0070 };
0071
0072 template<template<class...> class F, template<class...> class L1, class... T1, template<class...> class L2, class... T2, template<class...> class L3, class... T3> struct mp_transform_impl<F, L1<T1...>, L2<T2...>, L3<T3...>>
0073 {
0074 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
0075
0076 template<class... U> struct f { using type = F<U...>; };
0077
0078 using type = L1<typename f<T1, T2, T3>::type...>;
0079
0080 #else
0081
0082 using type = L1<F<T1,T2,T3>...>;
0083
0084 #endif
0085 };
0086
0087 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, == 1900 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 40800 )
0088
0089 template<class... L> using mp_same_size_1 = mp_same<mp_size<L>...>;
0090 template<class... L> struct mp_same_size_2: mp_defer<mp_same_size_1, L...> {};
0091
0092 #endif
0093
0094 struct list_size_mismatch
0095 {
0096 };
0097
0098 #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
0099
0100 template<template<class...> class F, class... L> struct mp_transform_cuda_workaround
0101 {
0102 using type = mp_if<mp_same<mp_size<L>...>, detail::mp_transform_impl<F, L...>, detail::list_size_mismatch>;
0103 };
0104
0105 #endif
0106
0107 }
0108
0109 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, == 1900 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 40800 )
0110
0111 template<template<class...> class F, class... L> using mp_transform = typename mp_if<typename detail::mp_same_size_2<L...>::type, detail::mp_transform_impl<F, L...>, detail::list_size_mismatch>::type;
0112
0113 #else
0114
0115 #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
0116
0117 template<template<class...> class F, class... L> using mp_transform = typename detail::mp_transform_cuda_workaround< F, L...>::type::type;
0118
0119 #else
0120
0121 template<template<class...> class F, class... L> using mp_transform = typename mp_if<mp_same<mp_size<L>...>, detail::mp_transform_impl<F, L...>, detail::list_size_mismatch>::type;
0122
0123 #endif
0124
0125 #endif
0126
0127 template<class Q, class... L> using mp_transform_q = mp_transform<Q::template fn, L...>;
0128
0129 namespace detail
0130 {
0131
0132 template<template<class...> class F, template<class...> class L1, class... T1, template<class...> class L2, class... T2, template<class...> class L3, class... T3, template<class...> class L4, class... T4, class... L> struct mp_transform_impl<F, L1<T1...>, L2<T2...>, L3<T3...>, L4<T4...>, L...>
0133 {
0134 using A1 = L1<mp_list<T1, T2, T3, T4>...>;
0135
0136 template<class V, class T> using _f = mp_transform<mp_push_back, V, T>;
0137
0138 using A2 = mp_fold<mp_list<L...>, A1, _f>;
0139
0140 template<class T> using _g = mp_apply<F, T>;
0141
0142 using type = mp_transform<_g, A2>;
0143 };
0144
0145 }
0146
0147
0148 namespace detail
0149 {
0150
0151 template<template<class...> class P, template<class...> class F, class... L> struct mp_transform_if_impl
0152 {
0153
0154
0155 using Qp = mp_quote<P>;
0156 using Qf = mp_quote<F>;
0157
0158 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
0159
0160 template<class... U> struct _f_ { using type = mp_eval_if_q<mp_not<mp_invoke_q<Qp, U...>>, mp_first<mp_list<U...>>, Qf, U...>; };
0161 template<class... U> using _f = typename _f_<U...>::type;
0162
0163 #else
0164
0165 template<class... U> using _f = mp_eval_if_q<mp_not<mp_invoke_q<Qp, U...>>, mp_first<mp_list<U...>>, Qf, U...>;
0166
0167 #endif
0168
0169 using type = mp_transform<_f, L...>;
0170 };
0171
0172 }
0173
0174 template<template<class...> class P, template<class...> class F, class... L> using mp_transform_if = typename detail::mp_transform_if_impl<P, F, L...>::type;
0175 template<class Qp, class Qf, class... L> using mp_transform_if_q = typename detail::mp_transform_if_impl<Qp::template fn, Qf::template fn, L...>::type;
0176
0177
0178 namespace detail
0179 {
0180
0181 template<template<class...> class P, class L1, class... L> struct mp_filter_impl
0182 {
0183 using Qp = mp_quote<P>;
0184
0185 template<class T1, class... T> using _f = mp_if< mp_invoke_q<Qp, T1, T...>, mp_list<T1>, mp_list<> >;
0186
0187 using _t1 = mp_transform<_f, L1, L...>;
0188 using _t2 = mp_apply<mp_append, _t1>;
0189
0190 using type = mp_assign<L1, _t2>;
0191 };
0192
0193 }
0194
0195 template<template<class...> class P, class... L> using mp_filter = typename detail::mp_filter_impl<P, L...>::type;
0196 template<class Q, class... L> using mp_filter_q = typename detail::mp_filter_impl<Q::template fn, L...>::type;
0197
0198
0199 namespace detail
0200 {
0201
0202 template<class L, class V> struct mp_fill_impl
0203 {
0204
0205 };
0206
0207 template<template<class...> class L, class... T, class V> struct mp_fill_impl<L<T...>, V>
0208 {
0209 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1900 )
0210
0211 template<class...> struct _f { using type = V; };
0212 using type = L<typename _f<T>::type...>;
0213
0214 #else
0215
0216 template<class...> using _f = V;
0217 using type = L<_f<T>...>;
0218
0219 #endif
0220 };
0221
0222 #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
0223
0224 template<template<auto...> class L, auto... A, class V> struct mp_fill_impl<L<A...>, V>
0225 {
0226 using type = L<((void)A, V::value)...>;
0227 };
0228
0229 #endif
0230
0231 }
0232
0233 template<class L, class V> using mp_fill = typename detail::mp_fill_impl<L, V>::type;
0234
0235
0236 template<class L, class V> using mp_contains = mp_to_bool<mp_count<L, V>>;
0237
0238
0239 namespace detail
0240 {
0241
0242 template<class L, std::size_t N> struct mp_repeat_c_impl
0243 {
0244 using _l1 = typename mp_repeat_c_impl<L, N/2>::type;
0245 using _l2 = typename mp_repeat_c_impl<L, N%2>::type;
0246
0247 using type = mp_append<_l1, _l1, _l2>;
0248 };
0249
0250 template<class L> struct mp_repeat_c_impl<L, 0>
0251 {
0252 using type = mp_clear<L>;
0253 };
0254
0255 template<class L> struct mp_repeat_c_impl<L, 1>
0256 {
0257 using type = L;
0258 };
0259
0260 }
0261
0262 template<class L, std::size_t N> using mp_repeat_c = typename detail::mp_repeat_c_impl<L, N>::type;
0263 template<class L, class N> using mp_repeat = typename detail::mp_repeat_c_impl<L, std::size_t{ N::value }>::type;
0264
0265
0266 namespace detail
0267 {
0268
0269 template<template<class...> class F, class P, class... L> struct mp_product_impl_2
0270 {
0271 };
0272
0273 template<template<class...> class F, class P> struct mp_product_impl_2<F, P>
0274 {
0275 using type = mp_list<mp_rename<P, F>>;
0276 };
0277
0278 template<template<class...> class F, class P, template<class...> class L1, class... T1, class... L> struct mp_product_impl_2<F, P, L1<T1...>, L...>
0279 {
0280 using type = mp_append<typename mp_product_impl_2<F, mp_push_back<P, T1>, L...>::type...>;
0281 };
0282
0283 template<template<class...> class F, class... L> struct mp_product_impl
0284 {
0285 };
0286
0287 template<template<class...> class F> struct mp_product_impl<F>
0288 {
0289 using type = mp_list< F<> >;
0290 };
0291
0292 template<template<class...> class F, class L1, class... L> struct mp_product_impl<F, L1, L...>
0293 {
0294 using type = mp_assign<L1, typename mp_product_impl_2<F, mp_list<>, L1, L...>::type>;
0295 };
0296
0297 }
0298
0299 template<template<class...> class F, class... L> using mp_product = typename detail::mp_product_impl<F, L...>::type;
0300 template<class Q, class... L> using mp_product_q = typename detail::mp_product_impl<Q::template fn, L...>::type;
0301
0302
0303 namespace detail
0304 {
0305
0306 template<class L, class L2, class En> struct mp_drop_impl;
0307
0308 template<template<class...> class L, class... T, template<class...> class L2, class... U> struct mp_drop_impl<L<T...>, L2<U...>, mp_true>
0309 {
0310 template<class... W> static mp_identity<L<W...>> f( U*..., mp_identity<W>*... );
0311
0312 using R = decltype( f( static_cast<mp_identity<T>*>(0) ... ) );
0313
0314 using type = typename R::type;
0315 };
0316
0317 }
0318
0319 template<class L, std::size_t N> using mp_drop_c = mp_assign<L, typename detail::mp_drop_impl<mp_rename<L, mp_list>, mp_repeat_c<mp_list<void>, N>, mp_bool<N <= mp_size<L>::value>>::type>;
0320
0321 template<class L, class N> using mp_drop = mp_drop_c<L, std::size_t{ N::value }>;
0322
0323
0324 namespace detail
0325 {
0326
0327 template<class S, class F> struct mp_from_sequence_impl;
0328
0329 template<template<class T, T... I> class S, class U, U... J, class F> struct mp_from_sequence_impl<S<U, J...>, F>
0330 {
0331 using type = mp_list_c<U, (F::value + J)...>;
0332 };
0333
0334 }
0335
0336 template<class S, class F = mp_int<0>> using mp_from_sequence = typename detail::mp_from_sequence_impl<S, F>::type;
0337
0338
0339 template<std::size_t N, std::size_t F = 0> using mp_iota_c = mp_from_sequence<make_index_sequence<N>, mp_size_t<F>>;
0340 template<class N, class F = mp_int<0>> using mp_iota = mp_from_sequence<make_integer_sequence<typename std::remove_const<decltype(N::value)>::type, N::value>, F>;
0341
0342
0343 namespace detail
0344 {
0345
0346 template<class L, std::size_t I> struct mp_at_c_impl;
0347
0348 #if defined(BOOST_MP11_HAS_TYPE_PACK_ELEMENT)
0349
0350 template<template<class...> class L, class... T, std::size_t I> struct mp_at_c_impl<L<T...>, I>
0351 {
0352 using type = __type_pack_element<I, T...>;
0353 };
0354
0355 #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO)
0356
0357 template<template<auto...> class L, auto... A, std::size_t I> struct mp_at_c_impl<L<A...>, I>
0358 {
0359 using type = __type_pack_element<I, mp_value<A>...>;
0360 };
0361
0362 #endif
0363
0364 #else
0365
0366 template<class L, std::size_t I> struct mp_at_c_impl
0367 {
0368 using _map = mp_transform<mp_list, mp_iota<mp_size<L> >, mp_rename<L, mp_list>>;
0369 using type = mp_second<mp_map_find<_map, mp_size_t<I> > >;
0370 };
0371
0372 #endif
0373
0374 #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
0375
0376 template<class L, std::size_t I> struct mp_at_c_cuda_workaround
0377 {
0378 using type = mp_if_c<(I < mp_size<L>::value), detail::mp_at_c_impl<L, I>, void>;
0379 };
0380
0381 #endif
0382
0383 }
0384
0385 #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
0386
0387 template<class L, std::size_t I> using mp_at_c = typename detail::mp_at_c_cuda_workaround< L, I >::type::type;
0388
0389 #else
0390
0391 template<class L, std::size_t I> using mp_at_c = typename mp_if_c<(I < mp_size<L>::value), detail::mp_at_c_impl<L, I>, void>::type;
0392
0393 #endif
0394
0395 template<class L, class I> using mp_at = mp_at_c<L, std::size_t{ I::value }>;
0396
0397
0398 namespace detail
0399 {
0400
0401 template<std::size_t N, class L, class E = void> struct mp_take_c_impl
0402 {
0403 };
0404
0405 template<template<class...> class L, class... T>
0406 struct mp_take_c_impl<0, L<T...>>
0407 {
0408 using type = L<>;
0409 };
0410
0411 template<template<class...> class L, class T1, class... T>
0412 struct mp_take_c_impl<1, L<T1, T...>>
0413 {
0414 using type = L<T1>;
0415 };
0416
0417 template<template<class...> class L, class T1, class T2, class... T>
0418 struct mp_take_c_impl<2, L<T1, T2, T...>>
0419 {
0420 using type = L<T1, T2>;
0421 };
0422
0423 template<template<class...> class L, class T1, class T2, class T3, class... T>
0424 struct mp_take_c_impl<3, L<T1, T2, T3, T...>>
0425 {
0426 using type = L<T1, T2, T3>;
0427 };
0428
0429 template<template<class...> class L, class T1, class T2, class T3, class T4, class... T>
0430 struct mp_take_c_impl<4, L<T1, T2, T3, T4, T...>>
0431 {
0432 using type = L<T1, T2, T3, T4>;
0433 };
0434
0435 template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class... T>
0436 struct mp_take_c_impl<5, L<T1, T2, T3, T4, T5, T...>>
0437 {
0438 using type = L<T1, T2, T3, T4, T5>;
0439 };
0440
0441 template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class... T>
0442 struct mp_take_c_impl<6, L<T1, T2, T3, T4, T5, T6, T...>>
0443 {
0444 using type = L<T1, T2, T3, T4, T5, T6>;
0445 };
0446
0447 template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class... T>
0448 struct mp_take_c_impl<7, L<T1, T2, T3, T4, T5, T6, T7, T...>>
0449 {
0450 using type = L<T1, T2, T3, T4, T5, T6, T7>;
0451 };
0452
0453 template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class... T>
0454 struct mp_take_c_impl<8, L<T1, T2, T3, T4, T5, T6, T7, T8, T...>>
0455 {
0456 using type = L<T1, T2, T3, T4, T5, T6, T7, T8>;
0457 };
0458
0459 template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class... T>
0460 struct mp_take_c_impl<9, L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>>
0461 {
0462 using type = L<T1, T2, T3, T4, T5, T6, T7, T8, T9>;
0463 };
0464
0465 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, std::size_t N>
0466 struct mp_take_c_impl<N, L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, typename std::enable_if<N >= 10>::type>
0467 {
0468 using type = mp_append<L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>, typename mp_take_c_impl<N-10, L<T...>>::type>;
0469 };
0470
0471 }
0472
0473 template<class L, std::size_t N> using mp_take_c = mp_assign<L, typename detail::mp_take_c_impl<N, mp_rename<L, mp_list>>::type>;
0474 template<class L, class N> using mp_take = mp_take_c<L, std::size_t{ N::value }>;
0475
0476
0477 template<class L> using mp_back = mp_at_c<L, mp_size<L>::value - 1>;
0478
0479
0480 template<class L> using mp_pop_back = mp_take_c<L, mp_size<L>::value - 1>;
0481
0482
0483 namespace detail
0484 {
0485
0486 template<class L, class V, class W> struct mp_replace_impl;
0487
0488 template<template<class...> class L, class... T, class V, class W> struct mp_replace_impl<L<T...>, V, W>
0489 {
0490 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 )
0491 template<class A> struct _f { using type = mp_if<std::is_same<A, V>, W, A>; };
0492 using type = L<typename _f<T>::type...>;
0493 #else
0494 template<class A> using _f = mp_if<std::is_same<A, V>, W, A>;
0495 using type = L<_f<T>...>;
0496 #endif
0497 };
0498
0499 }
0500
0501 template<class L, class V, class W> using mp_replace = typename detail::mp_replace_impl<L, V, W>::type;
0502
0503
0504 namespace detail
0505 {
0506
0507 template<class L, template<class...> class P, class W> struct mp_replace_if_impl;
0508
0509 template<template<class...> class L, class... T, template<class...> class P, class W> struct mp_replace_if_impl<L<T...>, P, W>
0510 {
0511 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
0512 template<class U> struct _f { using type = mp_if<P<U>, W, U>; };
0513 using type = L<typename _f<T>::type...>;
0514 #else
0515 template<class U> using _f = mp_if<P<U>, W, U>;
0516 using type = L<_f<T>...>;
0517 #endif
0518 };
0519
0520 }
0521
0522 template<class L, template<class...> class P, class W> using mp_replace_if = typename detail::mp_replace_if_impl<L, P, W>::type;
0523 template<class L, class Q, class W> using mp_replace_if_q = mp_replace_if<L, Q::template fn, W>;
0524
0525
0526
0527
0528
0529 namespace detail
0530 {
0531
0532 template<class L, class V> struct mp_remove_impl;
0533
0534 template<template<class...> class L, class... T, class V> struct mp_remove_impl<L<T...>, V>
0535 {
0536 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 )
0537 template<class U> struct _f { using type = mp_if<std::is_same<U, V>, mp_list<>, mp_list<U>>; };
0538 using type = mp_append<L<>, typename _f<T>::type...>;
0539 #else
0540 template<class U> using _f = mp_if<std::is_same<U, V>, mp_list<>, mp_list<U>>;
0541 using type = mp_append<L<>, _f<T>...>;
0542 #endif
0543 };
0544
0545 }
0546
0547 template<class L, class V> using mp_remove = typename detail::mp_remove_impl<L, V>::type;
0548
0549
0550
0551
0552
0553 namespace detail
0554 {
0555
0556 template<class L2> struct mp_flatten_impl
0557 {
0558 template<class T> using fn = mp_if<mp_similar<L2, T>, T, mp_list<T>>;
0559 };
0560
0561 }
0562
0563 template<class L, class L2 = mp_clear<L>> using mp_flatten = mp_apply<mp_append, mp_push_front<mp_transform_q<detail::mp_flatten_impl<L2>, L>, mp_clear<L>>>;
0564
0565
0566 namespace detail
0567 {
0568
0569 template<class L, template<class...> class P> struct mp_partition_impl;
0570
0571 template<template<class...> class L, class... T, template<class...> class P> struct mp_partition_impl<L<T...>, P>
0572 {
0573 using type = L<mp_copy_if<L<T...>, P>, mp_remove_if<L<T...>, P>>;
0574 };
0575
0576 }
0577
0578 template<class L, template<class...> class P> using mp_partition = typename detail::mp_partition_impl<L, P>::type;
0579 template<class L, class Q> using mp_partition_q = mp_partition<L, Q::template fn>;
0580
0581
0582 namespace detail
0583 {
0584
0585 template<class L, template<class...> class P> struct mp_sort_impl;
0586
0587 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 )
0588
0589 template<template<class...> class L, class... T, template<class...> class P> struct mp_sort_impl<L<T...>, P>
0590 {
0591 static_assert( sizeof...(T) == 0, "T... must be empty" );
0592 using type = L<>;
0593 };
0594
0595 #else
0596
0597 template<template<class...> class L, template<class...> class P> struct mp_sort_impl<L<>, P>
0598 {
0599 using type = L<>;
0600 };
0601
0602 #endif
0603
0604 template<template<class...> class L, class T1, template<class...> class P> struct mp_sort_impl<L<T1>, P>
0605 {
0606 using type = L<T1>;
0607 };
0608
0609 template<template<class...> class L, class T1, class... T, template<class...> class P> struct mp_sort_impl<L<T1, T...>, P>
0610 {
0611 template<class U> using F = P<U, T1>;
0612
0613 using part = mp_partition<L<T...>, F>;
0614
0615 using S1 = typename mp_sort_impl<mp_first<part>, P>::type;
0616 using S2 = typename mp_sort_impl<mp_second<part>, P>::type;
0617
0618 using type = mp_append<mp_push_back<S1, T1>, S2>;
0619 };
0620
0621 }
0622
0623 template<class L, template<class...> class P> using mp_sort = typename detail::mp_sort_impl<L, P>::type;
0624 template<class L, class Q> using mp_sort_q = mp_sort<L, Q::template fn>;
0625
0626
0627 namespace detail
0628 {
0629
0630 template<class L, std::size_t I, template<class...> class P> struct mp_nth_element_impl;
0631
0632 template<template<class...> class L, class T1, std::size_t I, template<class...> class P> struct mp_nth_element_impl<L<T1>, I, P>
0633 {
0634 static_assert( I == 0, "mp_nth_element index out of range" );
0635 using type = T1;
0636 };
0637
0638 template<template<class...> class L, class T1, class... T, std::size_t I, template<class...> class P> struct mp_nth_element_impl<L<T1, T...>, I, P>
0639 {
0640 static_assert( I < 1 + sizeof...(T), "mp_nth_element index out of range" );
0641
0642 template<class U> using F = P<U, T1>;
0643
0644 using part = mp_partition<L<T...>, F>;
0645
0646 using L1 = mp_first<part>;
0647 static std::size_t const N1 = mp_size<L1>::value;
0648
0649 using L2 = mp_second<part>;
0650
0651 #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 )
0652
0653 struct detail
0654 {
0655 struct mp_nth_element_impl_cuda_workaround
0656 {
0657 using type = mp_cond<
0658
0659 mp_bool<(I < N1)>, mp_nth_element_impl<L1, I, P>,
0660 mp_bool<(I == N1)>, mp_identity<T1>,
0661 mp_true, mp_nth_element_impl<L2, I - N1 - 1, P>
0662
0663 >;
0664 };
0665 };
0666
0667 using type = typename detail::mp_nth_element_impl_cuda_workaround::type::type;
0668
0669 #else
0670
0671 using type = typename mp_cond<
0672
0673 mp_bool<(I < N1)>, mp_nth_element_impl<L1, I, P>,
0674 mp_bool<(I == N1)>, mp_identity<T1>,
0675 mp_true, mp_nth_element_impl<L2, I - N1 - 1, P>
0676
0677 >::type;
0678
0679 #endif
0680 };
0681
0682 }
0683
0684 template<class L, std::size_t I, template<class...> class P> using mp_nth_element_c = typename detail::mp_nth_element_impl<L, I, P>::type;
0685 template<class L, class I, template<class...> class P> using mp_nth_element = typename detail::mp_nth_element_impl<L, std::size_t{ I::value }, P>::type;
0686 template<class L, class I, class Q> using mp_nth_element_q = mp_nth_element<L, I, Q::template fn>;
0687
0688
0689 namespace detail
0690 {
0691
0692 template<class L, class V> struct mp_find_impl;
0693
0694 #if BOOST_MP11_CLANG && defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS )
0695
0696 struct mp_index_holder
0697 {
0698 std::size_t i_;
0699 bool f_;
0700 };
0701
0702 constexpr inline mp_index_holder operator+( mp_index_holder const & v, bool f )
0703 {
0704 if( v.f_ )
0705 {
0706 return v;
0707 }
0708 else if( f )
0709 {
0710 return { v.i_, true };
0711 }
0712 else
0713 {
0714 return { v.i_ + 1, false };
0715 }
0716 }
0717
0718 template<template<class...> class L, class... T, class V> struct mp_find_impl<L<T...>, V>
0719 {
0720 static constexpr mp_index_holder _v{ 0, false };
0721 using type = mp_size_t< (_v + ... + std::is_same<T, V>::value).i_ >;
0722 };
0723
0724 #elif !defined( BOOST_MP11_NO_CONSTEXPR )
0725
0726 template<template<class...> class L, class V> struct mp_find_impl<L<>, V>
0727 {
0728 using type = mp_size_t<0>;
0729 };
0730
0731 #if defined( BOOST_MP11_HAS_CXX14_CONSTEXPR )
0732
0733 constexpr std::size_t cx_find_index( bool const * first, bool const * last )
0734 {
0735 std::size_t m = 0;
0736
0737 while( first != last && !*first )
0738 {
0739 ++m;
0740 ++first;
0741 }
0742
0743 return m;
0744 }
0745
0746 #else
0747
0748 constexpr std::size_t cx_find_index( bool const * first, bool const * last )
0749 {
0750 return first == last || *first? 0: 1 + cx_find_index( first + 1, last );
0751 }
0752
0753 #endif
0754
0755 template<template<class...> class L, class... T, class V> struct mp_find_impl<L<T...>, V>
0756 {
0757 static constexpr bool _v[] = { std::is_same<T, V>::value... };
0758 using type = mp_size_t< cx_find_index( _v, _v + sizeof...(T) ) >;
0759 };
0760
0761 #else
0762
0763 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 )
0764
0765 template<template<class...> class L, class... T, class V> struct mp_find_impl<L<T...>, V>
0766 {
0767 static_assert( sizeof...(T) == 0, "T... must be empty" );
0768 using type = mp_size_t<0>;
0769 };
0770
0771 #else
0772
0773 template<template<class...> class L, class V> struct mp_find_impl<L<>, V>
0774 {
0775 using type = mp_size_t<0>;
0776 };
0777
0778 #endif
0779
0780 template<template<class...> class L, class... T, class V> struct mp_find_impl<L<V, T...>, V>
0781 {
0782 using type = mp_size_t<0>;
0783 };
0784
0785 template<template<class...> class L, class T1, class... T, class V> struct mp_find_impl<L<T1, T...>, V>
0786 {
0787 using _r = typename mp_find_impl<mp_list<T...>, V>::type;
0788 using type = mp_size_t<1 + _r::value>;
0789 };
0790
0791 #endif
0792
0793 }
0794
0795 template<class L, class V> using mp_find = typename detail::mp_find_impl<L, V>::type;
0796
0797
0798 namespace detail
0799 {
0800
0801 template<class L, template<class...> class P> struct mp_find_if_impl;
0802
0803 #if BOOST_MP11_CLANG && defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS )
0804
0805 template<template<class...> class L, class... T, template<class...> class P> struct mp_find_if_impl<L<T...>, P>
0806 {
0807 static constexpr mp_index_holder _v{ 0, false };
0808 using type = mp_size_t< (_v + ... + P<T>::value).i_ >;
0809 };
0810
0811 #elif !defined( BOOST_MP11_NO_CONSTEXPR )
0812
0813 template<template<class...> class L, template<class...> class P> struct mp_find_if_impl<L<>, P>
0814 {
0815 using type = mp_size_t<0>;
0816 };
0817
0818 template<template<class...> class L, class... T, template<class...> class P> struct mp_find_if_impl<L<T...>, P>
0819 {
0820 static constexpr bool _v[] = { P<T>::value... };
0821 using type = mp_size_t< cx_find_index( _v, _v + sizeof...(T) ) >;
0822 };
0823
0824 #else
0825
0826 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 )
0827
0828 template<template<class...> class L, class... T, template<class...> class P> struct mp_find_if_impl<L<T...>, P>
0829 {
0830 static_assert( sizeof...(T) == 0, "T... must be empty" );
0831 using type = mp_size_t<0>;
0832 };
0833
0834 #else
0835
0836 template<template<class...> class L, template<class...> class P> struct mp_find_if_impl<L<>, P>
0837 {
0838 using type = mp_size_t<0>;
0839 };
0840
0841 #endif
0842
0843 template<class L, template<class...> class P> struct mp_find_if_impl_2
0844 {
0845 using _r = typename mp_find_if_impl<L, P>::type;
0846 using type = mp_size_t<1 + _r::value>;
0847 };
0848
0849 template<template<class...> class L, class T1, class... T, template<class...> class P> struct mp_find_if_impl<L<T1, T...>, P>
0850 {
0851 using type = typename mp_if<P<T1>, mp_identity<mp_size_t<0>>, mp_find_if_impl_2<mp_list<T...>, P>>::type;
0852 };
0853
0854 #endif
0855
0856 }
0857
0858 template<class L, template<class...> class P> using mp_find_if = typename detail::mp_find_if_impl<L, P>::type;
0859 template<class L, class Q> using mp_find_if_q = mp_find_if<L, Q::template fn>;
0860
0861
0862 namespace detail
0863 {
0864
0865 template<class L> struct mp_reverse_impl;
0866
0867 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 )
0868
0869 template<template<class...> class L, class... T> struct mp_reverse_impl<L<T...>>
0870 {
0871 static_assert( sizeof...(T) == 0, "T... must be empty" );
0872 using type = L<>;
0873 };
0874
0875 #else
0876
0877 template<template<class...> class L> struct mp_reverse_impl<L<>>
0878 {
0879 using type = L<>;
0880 };
0881
0882 #endif
0883
0884 template<template<class...> class L, class T1> struct mp_reverse_impl<L<T1>>
0885 {
0886 using type = L<T1>;
0887 };
0888
0889 template<template<class...> class L, class T1, class T2> struct mp_reverse_impl<L<T1, T2>>
0890 {
0891 using type = L<T2, T1>;
0892 };
0893
0894 template<template<class...> class L, class T1, class T2, class T3> struct mp_reverse_impl<L<T1, T2, T3>>
0895 {
0896 using type = L<T3, T2, T1>;
0897 };
0898
0899 template<template<class...> class L, class T1, class T2, class T3, class T4> struct mp_reverse_impl<L<T1, T2, T3, T4>>
0900 {
0901 using type = L<T4, T3, T2, T1>;
0902 };
0903
0904 template<template<class...> class L, class T1, class T2, class T3, class T4, class T5> struct mp_reverse_impl<L<T1, T2, T3, T4, T5>>
0905 {
0906 using type = L<T5, T4, T3, T2, T1>;
0907 };
0908
0909 template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6> struct mp_reverse_impl<L<T1, T2, T3, T4, T5, T6>>
0910 {
0911 using type = L<T6, T5, T4, T3, T2, T1>;
0912 };
0913
0914 template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7> struct mp_reverse_impl<L<T1, T2, T3, T4, T5, T6, T7>>
0915 {
0916 using type = L<T7, T6, T5, T4, T3, T2, T1>;
0917 };
0918
0919 template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8> struct mp_reverse_impl<L<T1, T2, T3, T4, T5, T6, T7, T8>>
0920 {
0921 using type = L<T8, T7, T6, T5, T4, T3, T2, T1>;
0922 };
0923
0924 template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9> struct mp_reverse_impl<L<T1, T2, T3, T4, T5, T6, T7, T8, T9>>
0925 {
0926 using type = L<T9, T8, T7, T6, T5, T4, T3, T2, T1>;
0927 };
0928
0929 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> struct mp_reverse_impl<L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>>
0930 {
0931 using type = mp_push_back<typename mp_reverse_impl<L<T...>>::type, T10, T9, T8, T7, T6, T5, T4, T3, T2, T1>;
0932 };
0933
0934 }
0935
0936 template<class L> using mp_reverse = typename detail::mp_reverse_impl<L>::type;
0937
0938
0939
0940
0941
0942 namespace detail
0943 {
0944
0945 template<class L, class V, template<class...> class F> struct mp_reverse_fold_impl;
0946
0947 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 )
0948
0949 template<template<class...> class L, class... T, class V, template<class...> class F> struct mp_reverse_fold_impl<L<T...>, V, F>
0950 {
0951 static_assert( sizeof...(T) == 0, "T... must be empty" );
0952 using type = V;
0953 };
0954
0955 #else
0956
0957 template<template<class...> class L, class V, template<class...> class F> struct mp_reverse_fold_impl<L<>, V, F>
0958 {
0959 using type = V;
0960 };
0961
0962 #endif
0963
0964 template<template<class...> class L, class T1, class... T, class V, template<class...> class F> struct mp_reverse_fold_impl<L<T1, T...>, V, F>
0965 {
0966 using rest = typename mp_reverse_fold_impl<L<T...>, V, F>::type;
0967 using type = F<T1, rest>;
0968 };
0969
0970 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_reverse_fold_impl<L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, V, F>
0971 {
0972 using rest = typename mp_reverse_fold_impl<L<T...>, V, F>::type;
0973 using type = F<T1, F<T2, F<T3, F<T4, F<T5, F<T6, F<T7, F<T8, F<T9, F<T10, rest> > > > > > > > > >;
0974 };
0975
0976 }
0977
0978 template<class L, class V, template<class...> class F> using mp_reverse_fold = typename detail::mp_reverse_fold_impl<L, V, F>::type;
0979 template<class L, class V, class Q> using mp_reverse_fold_q = mp_reverse_fold<L, V, Q::template fn>;
0980
0981
0982 namespace detail
0983 {
0984
0985 template<class L> struct mp_unique_impl;
0986
0987 template<template<class...> class L, class... T> struct mp_unique_impl<L<T...>>
0988 {
0989 using type = mp_set_push_back<L<>, T...>;
0990 };
0991
0992 }
0993
0994 template<class L> using mp_unique = typename detail::mp_unique_impl<L>::type;
0995
0996
0997 namespace detail
0998 {
0999
1000 template<template<class...> class P> struct mp_unique_if_push_back
1001 {
1002 template<class...> struct impl
1003 {
1004 };
1005
1006 template<template<class...> class L, class... Ts, class T>
1007 struct impl<L<Ts...>, T>
1008 {
1009 using type = mp_if<mp_any<P<Ts, T>...>, L<Ts...>, L<Ts..., T>>;
1010 };
1011
1012 template<class... T> using fn = typename impl<T...>::type;
1013 };
1014
1015 }
1016
1017 template<class L, template<class...> class P>
1018 using mp_unique_if = mp_fold_q<L, mp_clear<L>, detail::mp_unique_if_push_back<P>>;
1019
1020 template<class L, class Q> using mp_unique_if_q = mp_unique_if<L, Q::template fn>;
1021
1022
1023 template<class L, template<class...> class P> using mp_all_of = mp_bool< mp_count_if<L, P>::value == mp_size<L>::value >;
1024 template<class L, class Q> using mp_all_of_q = mp_all_of<L, Q::template fn>;
1025
1026
1027 template<class L, template<class...> class P> using mp_none_of = mp_bool< mp_count_if<L, P>::value == 0 >;
1028 template<class L, class Q> using mp_none_of_q = mp_none_of<L, Q::template fn>;
1029
1030
1031 template<class L, template<class...> class P> using mp_any_of = mp_bool< mp_count_if<L, P>::value != 0 >;
1032 template<class L, class Q> using mp_any_of_q = mp_any_of<L, Q::template fn>;
1033
1034
1035 namespace detail
1036 {
1037
1038 template<class L, class I, class W> struct mp_replace_at_impl
1039 {
1040 static_assert( I::value >= 0, "mp_replace_at<L, I, W>: I must not be negative" );
1041
1042 template<class T1, class T2> using _p = std::is_same<T2, mp_size_t<I::value>>;
1043 template<class T1, class T2> using _f = W;
1044
1045 using type = mp_transform_if<_p, _f, L, mp_iota<mp_size<L> > >;
1046 };
1047
1048 }
1049
1050 template<class L, class I, class W> using mp_replace_at = typename detail::mp_replace_at_impl<L, I, W>::type;
1051 template<class L, std::size_t I, class W> using mp_replace_at_c = typename detail::mp_replace_at_impl<L, mp_size_t<I>, W>::type;
1052
1053
1054 namespace detail
1055 {
1056
1057 template<class... T, class F> BOOST_MP11_CONSTEXPR F mp_for_each_impl( mp_list<T...>, F && f )
1058 {
1059 using A = int[sizeof...(T)];
1060 return (void)A{ ((void)f(T()), 0)... }, std::forward<F>(f);
1061 }
1062
1063 template<class F> BOOST_MP11_CONSTEXPR F mp_for_each_impl( mp_list<>, F && f )
1064 {
1065 return std::forward<F>(f);
1066 }
1067
1068 }
1069
1070 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, >= 1900 )
1071
1072
1073
1074 template<class L, class F> BOOST_MP11_CONSTEXPR mp_if_c<mp_size<L>::value <= 1024, F> mp_for_each( F && f )
1075 {
1076 return detail::mp_for_each_impl( mp_rename<L, mp_list>(), std::forward<F>(f) );
1077 }
1078
1079 template<class L, class F> BOOST_MP11_CONSTEXPR mp_if_c<mp_size<L>::value >= 1025, F> mp_for_each( F && f )
1080 {
1081 using L2 = mp_rename<L, mp_list>;
1082
1083 using L3 = mp_take_c<L2, 1024>;
1084 using L4 = mp_drop_c<L2, 1024>;
1085
1086 return mp_for_each<L4>( mp_for_each<L3>( std::forward<F>(f) ) );
1087 }
1088
1089 #else
1090
1091 template<class L, class F> BOOST_MP11_CONSTEXPR F mp_for_each( F && f )
1092 {
1093 return detail::mp_for_each_impl( mp_rename<L, mp_list>(), std::forward<F>(f) );
1094 }
1095
1096 #endif
1097
1098
1099 template<class L, class I, class... T> using mp_insert = mp_append<mp_take<L, I>, mp_push_front<mp_drop<L, I>, T...>>;
1100
1101
1102 template<class L, std::size_t I, class... T> using mp_insert_c = mp_append<mp_take_c<L, I>, mp_push_front<mp_drop_c<L, I>, T...>>;
1103
1104
1105 template<class L, class I, class J> using mp_erase = mp_append<mp_take<L, I>, mp_drop<L, J>>;
1106
1107
1108 template<class L, std::size_t I, std::size_t J> using mp_erase_c = mp_append<mp_take_c<L, I>, mp_drop_c<L, J>>;
1109
1110
1111
1112 namespace detail {
1113
1114 template<class L1, class L2>
1115 struct mp_starts_with_impl { };
1116
1117 template<template<class...> class L1, class... T1, template<class...> class L2,
1118 class... T2>
1119 struct mp_starts_with_impl<L1<T1...>, L2<T2...> > {
1120 template<class L>
1121 static mp_false check(L);
1122
1123 template<class... T>
1124 static mp_true check(mp_list<T2..., T...>);
1125
1126 using type = decltype(check(mp_list<T1...>()));
1127 };
1128
1129 }
1130
1131 template<class L1, class L2>
1132 using mp_starts_with = typename detail::mp_starts_with_impl<L1, L2>::type;
1133
1134
1135 namespace detail
1136 {
1137
1138
1139 template<std::size_t Ln, std::size_t N> using canonical_left_rotation = mp_size_t<N % (Ln == 0? 1: Ln)>;
1140
1141
1142 template<std::size_t Ln, std::size_t N> using canonical_right_rotation = mp_size_t<Ln - N % (Ln == 0? 1: Ln)>;
1143
1144
1145 template<class L, class N, class L2 = mp_rename<L, mp_list>> using mp_rotate_impl = mp_assign<L, mp_append< mp_drop<L2, N>, mp_take<L2, N> >>;
1146
1147 }
1148
1149 template<class L, std::size_t N> using mp_rotate_left_c = detail::mp_rotate_impl<L, detail::canonical_left_rotation<mp_size<L>::value, N>>;
1150 template<class L, class N> using mp_rotate_left = mp_rotate_left_c<L, std::size_t{ N::value }>;
1151
1152
1153 template<class L, std::size_t N> using mp_rotate_right_c = mp_rotate_left<L, detail::canonical_right_rotation<mp_size<L>::value, N>>;
1154 template<class L, class N> using mp_rotate_right = mp_rotate_right_c<L, std::size_t{ N::value }>;
1155
1156
1157
1158
1159
1160
1161 namespace detail
1162 {
1163
1164 template<class L> struct mp_power_set_impl;
1165
1166 }
1167
1168 template<class L> using mp_power_set = typename detail::mp_power_set_impl<L>::type;
1169
1170 namespace detail
1171 {
1172
1173 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 )
1174
1175 template<template<class...> class L, class... T> struct mp_power_set_impl< L<T...> >
1176 {
1177 static_assert( sizeof...(T) == 0, "T... must be empty" );
1178 using type = L< L<> >;
1179 };
1180
1181 #else
1182
1183 template<template<class...> class L> struct mp_power_set_impl< L<> >
1184 {
1185 using type = L< L<> >;
1186 };
1187
1188 #endif
1189
1190 template<template<class...> class L, class T1, class... T> struct mp_power_set_impl< L<T1, T...> >
1191 {
1192 using S1 = mp_power_set< L<T...> >;
1193
1194 template<class L2> using _f = mp_push_front<L2, T1>;
1195
1196 using S2 = mp_transform<_f, S1>;
1197
1198 using type = mp_append< S1, S2 >;
1199 };
1200
1201 }
1202
1203
1204 namespace detail
1205 {
1206
1207 template<template<class...> class F> struct mp_partial_sum_impl_f
1208 {
1209 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1900 )
1210
1211 template<class V, class T> using fn = mp_list<F<mp_first<V>, T>, mp_push_back<mp_second<V>, F<mp_first<V>, T>> >;
1212
1213 #else
1214
1215 template<class V, class T, class N = F<mp_first<V>, T>> using fn = mp_list<N, mp_push_back<mp_second<V>, N>>;
1216
1217 #endif
1218 };
1219
1220 }
1221
1222 template<class L, class V, template<class...> class F> using mp_partial_sum = mp_second<mp_fold_q<L, mp_list<V, mp_clear<L>>, detail::mp_partial_sum_impl_f<F>> >;
1223 template<class L, class V, class Q> using mp_partial_sum_q = mp_partial_sum<L, V, Q::template fn>;
1224
1225
1226 namespace detail
1227 {
1228
1229 template<class V, template<class...> class F, template<class...> class R, class N> struct mp_iterate_impl;
1230
1231 }
1232
1233 template<class V, template<class...> class F, template<class...> class R> using mp_iterate = typename detail::mp_iterate_impl<V, F, R, mp_valid<R, V>>::type;
1234
1235 namespace detail
1236 {
1237
1238 template<class V, template<class...> class F, template<class...> class R> struct mp_iterate_impl<V, F, R, mp_false>
1239 {
1240 template<class X> using _f = mp_list<F<X>>;
1241 using type = mp_eval_or<mp_list<>, _f, V>;
1242 };
1243
1244 template<class V, template<class...> class F, template<class...> class R> struct mp_iterate_impl<V, F, R, mp_true>
1245 {
1246 using type = mp_push_front<mp_iterate<R<V>, F, R>, F<V>>;
1247 };
1248
1249 }
1250
1251 template<class V, class Qf, class Qr> using mp_iterate_q = mp_iterate<V, Qf::template fn, Qr::template fn>;
1252
1253
1254 namespace detail
1255 {
1256
1257 template<class L, class Q> using mp_pairwise_fold_impl = mp_transform_q<Q, mp_pop_back<L>, mp_pop_front<L>>;
1258
1259 }
1260
1261 template<class L, class Q> using mp_pairwise_fold_q = mp_eval_if<mp_empty<L>, mp_clear<L>, detail::mp_pairwise_fold_impl, L, Q>;
1262 template<class L, template<class...> class F> using mp_pairwise_fold = mp_pairwise_fold_q<L, mp_quote<F>>;
1263
1264
1265 namespace detail
1266 {
1267
1268 template<class L, class S> struct mp_intersperse_impl
1269 {
1270 };
1271
1272 #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 )
1273
1274 template<template<class...> class L, class... T, class S> struct mp_intersperse_impl<L<T...>, S>
1275 {
1276 static_assert( sizeof...(T) == 0, "T... must be empty" );
1277 using type = L<>;
1278 };
1279
1280 #else
1281
1282 template<template<class...> class L, class S> struct mp_intersperse_impl<L<>, S>
1283 {
1284 using type = L<>;
1285 };
1286
1287 #endif
1288
1289 template<template<class...> class L, class T1, class... T, class S> struct mp_intersperse_impl<L<T1, T...>, S>
1290 {
1291 using type = mp_append<L<T1>, L<S, T>...>;
1292 };
1293
1294 }
1295
1296 template<class L, class S> using mp_intersperse = typename detail::mp_intersperse_impl<L, S>::type;
1297
1298
1299 namespace detail
1300 {
1301
1302 template<class L, class S, class J> struct mp_split_impl;
1303
1304 }
1305
1306 template<class L, class S> using mp_split = typename detail::mp_split_impl<L, S, mp_find<L, S>>::type;
1307
1308 namespace detail
1309 {
1310
1311 template<class L, class S, class J> using mp_split_impl_ = mp_push_front<mp_split<mp_drop_c<L, J::value + 1>, S>, mp_take<L, J>>;
1312
1313 template<class L, class S, class J> struct mp_split_impl
1314 {
1315 using type = mp_eval_if_c<mp_size<L>::value == J::value, mp_push_back<mp_clear<L>, L>, mp_split_impl_, L, S, J>;
1316 };
1317
1318 }
1319
1320
1321
1322 template<class L, class S> using mp_join = mp_apply<mp_append, mp_intersperse<L, mp_list<S>>>;
1323
1324 }
1325 }
1326
1327 #endif