#ifndef BOOST_MP11_ALGORITHM_HPP_INCLUDED #define BOOST_MP11_ALGORITHM_HPP_INCLUDED // Copyright 2015-2019 Peter Dimov // // Distributed under 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace mp11 { // mp_transform namespace detail { template class F, class... L> struct mp_transform_impl { }; template class F, template class L, class... T> struct mp_transform_impl> { #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) template struct f { using type = F; }; using type = L::type...>; #else using type = L...>; #endif }; template class F, template class L1, class... T1, template class L2, class... T2> struct mp_transform_impl, L2> { #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) template struct f { using type = F; }; using type = L1::type...>; #else using type = L1...>; #endif }; template class F, template class L1, class... T1, template class L2, class... T2, template class L3, class... T3> struct mp_transform_impl, L2, L3> { #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) template struct f { using type = F; }; using type = L1::type...>; #else using type = L1...>; #endif }; #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, == 1900 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 40800 ) template using mp_same_size_1 = mp_same...>; template struct mp_same_size_2: mp_defer {}; #endif struct list_size_mismatch { }; #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) template class F, class... L> struct mp_transform_cuda_workaround { using type = mp_if...>, detail::mp_transform_impl, detail::list_size_mismatch>; }; #endif } // namespace detail #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, == 1900 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 40800 ) template class F, class... L> using mp_transform = typename mp_if::type, detail::mp_transform_impl, detail::list_size_mismatch>::type; #else #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) template class F, class... L> using mp_transform = typename detail::mp_transform_cuda_workaround< F, L...>::type::type; #else template class F, class... L> using mp_transform = typename mp_if...>, detail::mp_transform_impl, detail::list_size_mismatch>::type; #endif #endif template using mp_transform_q = mp_transform; namespace detail { template class F, template class L1, class... T1, template class L2, class... T2, template class L3, class... T3, template class L4, class... T4, class... L> struct mp_transform_impl, L2, L3, L4, L...> { using A1 = L1...>; template using _f = mp_transform; using A2 = mp_fold, A1, _f>; template using _g = mp_apply; using type = mp_transform<_g, A2>; }; } // namespace detail // mp_transform_if namespace detail { template class P, template class F, class... L> struct mp_transform_if_impl { // the stupid quote-unquote dance avoids "pack expansion used as argument for non-pack parameter of alias template" using Qp = mp_quote

; using Qf = mp_quote; #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) template struct _f_ { using type = mp_eval_if_q>, mp_first>, Qf, U...>; }; template using _f = typename _f_::type; #else template using _f = mp_eval_if_q>, mp_first>, Qf, U...>; #endif using type = mp_transform<_f, L...>; }; } // namespace detail template class P, template class F, class... L> using mp_transform_if = typename detail::mp_transform_if_impl::type; template using mp_transform_if_q = typename detail::mp_transform_if_impl::type; // mp_filter namespace detail { template class P, class L1, class... L> struct mp_filter_impl { using Qp = mp_quote

; template using _f = mp_if< mp_invoke_q, mp_list, mp_list<> >; using _t1 = mp_transform<_f, L1, L...>; using _t2 = mp_apply; using type = mp_assign; }; } // namespace detail template class P, class... L> using mp_filter = typename detail::mp_filter_impl::type; template using mp_filter_q = typename detail::mp_filter_impl::type; // mp_fill namespace detail { template struct mp_fill_impl; template class L, class... T, class V> struct mp_fill_impl, V> { #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1900 ) template struct _f { using type = V; }; using type = L::type...>; #else template using _f = V; using type = L<_f...>; #endif }; } // namespace detail template using mp_fill = typename detail::mp_fill_impl::type; // mp_contains template using mp_contains = mp_to_bool>; // mp_repeat(_c) namespace detail { template struct mp_repeat_c_impl { using _l1 = typename mp_repeat_c_impl::type; using _l2 = typename mp_repeat_c_impl::type; using type = mp_append<_l1, _l1, _l2>; }; template struct mp_repeat_c_impl { using type = mp_clear; }; template struct mp_repeat_c_impl { using type = L; }; } // namespace detail template using mp_repeat_c = typename detail::mp_repeat_c_impl::type; template using mp_repeat = typename detail::mp_repeat_c_impl::type; // mp_product namespace detail { template class F, class P, class... L> struct mp_product_impl_2; template class F, class P> struct mp_product_impl_2 { using type = mp_list>; }; template class F, class P, template class L1, class... T1, class... L> struct mp_product_impl_2, L...> { using type = mp_append, L...>::type...>; }; template class F, class... L> struct mp_product_impl; template class F, class L1, class... L> struct mp_product_impl { using type = mp_assign, L1, L...>::type>; }; } // namespace detail template class F, class... L> using mp_product = typename detail::mp_product_impl::type; template using mp_product_q = typename detail::mp_product_impl::type; // mp_drop(_c) namespace detail { template struct mp_drop_impl; template class L, class... T, template class L2, class... U> struct mp_drop_impl, L2> { template static mp_identity> f( U*..., mp_identity*... ); using R = decltype( f( (mp_identity*)0 ... ) ); using type = typename R::type; }; } // namespace detail template using mp_drop_c = typename detail::mp_drop_impl, N>>::type; template using mp_drop = typename detail::mp_drop_impl, N>>::type; // mp_from_sequence namespace detail { template struct mp_from_sequence_impl; template class S, class U, U... J> struct mp_from_sequence_impl> { using type = mp_list...>; }; } // namespace detail template using mp_from_sequence = typename detail::mp_from_sequence_impl::type; // mp_iota(_c) template using mp_iota_c = mp_from_sequence>; template using mp_iota = mp_from_sequence::type, N::value>>; // mp_at(_c) namespace detail { template struct mp_at_c_impl; #if defined(BOOST_MP11_HAS_TYPE_PACK_ELEMENT) template class L, class... T, std::size_t I> struct mp_at_c_impl, I> { using type = __type_pack_element; }; #else template struct mp_at_c_impl { using _map = mp_transform >, L>; using type = mp_second > >; }; #endif #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) template struct mp_at_c_cuda_workaround { using type = mp_if_c<(I < mp_size::value), detail::mp_at_c_impl, void>; }; #endif } // namespace detail #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) template using mp_at_c = typename detail::mp_at_c_cuda_workaround< L, I >::type::type; #else template using mp_at_c = typename mp_if_c<(I < mp_size::value), detail::mp_at_c_impl, void>::type; #endif template using mp_at = mp_at_c; // mp_take(_c) namespace detail { template struct mp_take_c_impl { }; template class L, class... T> struct mp_take_c_impl<0, L> { using type = L<>; }; template class L, class T1, class... T> struct mp_take_c_impl<1, L> { using type = L; }; template class L, class T1, class T2, class... T> struct mp_take_c_impl<2, L> { using type = L; }; template class L, class T1, class T2, class T3, class... T> struct mp_take_c_impl<3, L> { using type = L; }; template class L, class T1, class T2, class T3, class T4, class... T> struct mp_take_c_impl<4, L> { using type = L; }; template class L, class T1, class T2, class T3, class T4, class T5, class... T> struct mp_take_c_impl<5, L> { using type = L; }; template class L, class T1, class T2, class T3, class T4, class T5, class T6, class... T> struct mp_take_c_impl<6, L> { using type = L; }; template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class... T> struct mp_take_c_impl<7, L> { using type = L; }; template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class... T> struct mp_take_c_impl<8, L> { using type = L; }; template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class... T> struct mp_take_c_impl<9, L> { using type = L; }; template 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> struct mp_take_c_impl, typename std::enable_if= 10>::type> { using type = mp_append, typename mp_take_c_impl>::type>; }; } // namespace detail template using mp_take_c = typename detail::mp_take_c_impl::type; template using mp_take = typename detail::mp_take_c_impl::type; // mp_back template using mp_back = mp_at_c::value - 1>; // mp_pop_back template using mp_pop_back = mp_take_c::value - 1>; // mp_replace namespace detail { template struct mp_replace_impl; template class L, class... T, class V, class W> struct mp_replace_impl, V, W> { #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) template struct _f { using type = mp_if, W, A>; }; using type = L::type...>; #else template using _f = mp_if, W, A>; using type = L<_f...>; #endif }; } // namespace detail template using mp_replace = typename detail::mp_replace_impl::type; // mp_replace_if namespace detail { template class P, class W> struct mp_replace_if_impl; template class L, class... T, template class P, class W> struct mp_replace_if_impl, P, W> { #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) template struct _f { using type = mp_if, W, U>; }; using type = L::type...>; #else template using _f = mp_if, W, U>; using type = L<_f...>; #endif }; } // namespace detail template class P, class W> using mp_replace_if = typename detail::mp_replace_if_impl::type; template using mp_replace_if_q = mp_replace_if; // mp_copy_if // in detail/mp_copy_if.hpp // mp_remove namespace detail { template struct mp_remove_impl; template class L, class... T, class V> struct mp_remove_impl, V> { #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) template struct _f { using type = mp_if, mp_list<>, mp_list>; }; using type = mp_append, typename _f::type...>; #else template using _f = mp_if, mp_list<>, mp_list>; using type = mp_append, _f...>; #endif }; } // namespace detail template using mp_remove = typename detail::mp_remove_impl::type; // mp_remove_if // in detail/mp_remove_if.hpp // mp_partition namespace detail { template class P> struct mp_partition_impl; template class L, class... T, template class P> struct mp_partition_impl, P> { using type = L, P>, mp_remove_if, P>>; }; } // namespace detail template class P> using mp_partition = typename detail::mp_partition_impl::type; template using mp_partition_q = mp_partition; // mp_sort namespace detail { template class P> struct mp_sort_impl; #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) template class L, class... T, template class P> struct mp_sort_impl, P> { static_assert( sizeof...(T) == 0, "T... must be empty" ); using type = L<>; }; #else template class L, template class P> struct mp_sort_impl, P> { using type = L<>; }; #endif template class L, class T1, template class P> struct mp_sort_impl, P> { using type = L; }; template class L, class T1, class... T, template class P> struct mp_sort_impl, P> { template using F = P; using part = mp_partition, F>; using S1 = typename mp_sort_impl, P>::type; using S2 = typename mp_sort_impl, P>::type; using type = mp_append, S2>; }; } // namespace detail template class P> using mp_sort = typename detail::mp_sort_impl::type; template using mp_sort_q = mp_sort; // mp_nth_element(_c) namespace detail { template class P> struct mp_nth_element_impl; template class L, class T1, std::size_t I, template class P> struct mp_nth_element_impl, I, P> { static_assert( I == 0, "mp_nth_element index out of range" ); using type = T1; }; template class L, class T1, class... T, std::size_t I, template class P> struct mp_nth_element_impl, I, P> { static_assert( I < 1 + sizeof...(T), "mp_nth_element index out of range" ); template using F = P; using part = mp_partition, F>; using L1 = mp_first; static std::size_t const N1 = mp_size::value; using L2 = mp_second; #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) struct detail { struct mp_nth_element_impl_cuda_workaround { using type = mp_cond< mp_bool<(I < N1)>, mp_nth_element_impl, mp_bool<(I == N1)>, mp_identity, mp_true, mp_nth_element_impl >; }; }; using type = typename detail::mp_nth_element_impl_cuda_workaround::type::type; #else using type = typename mp_cond< mp_bool<(I < N1)>, mp_nth_element_impl, mp_bool<(I == N1)>, mp_identity, mp_true, mp_nth_element_impl >::type; #endif }; } // namespace detail template class P> using mp_nth_element_c = typename detail::mp_nth_element_impl::type; template class P> using mp_nth_element = typename detail::mp_nth_element_impl::type; template using mp_nth_element_q = mp_nth_element; // mp_find namespace detail { template struct mp_find_impl; #if BOOST_MP11_CLANG && defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) struct mp_index_holder { std::size_t i_; bool f_; }; constexpr inline mp_index_holder operator+( mp_index_holder const & v, bool f ) { if( v.f_ ) { return v; } else if( f ) { return { v.i_, true }; } else { return { v.i_ + 1, false }; } } template class L, class... T, class V> struct mp_find_impl, V> { static constexpr mp_index_holder _v{ 0, false }; using type = mp_size_t< (_v + ... + std::is_same::value).i_ >; }; #elif !defined( BOOST_MP11_NO_CONSTEXPR ) template class L, class V> struct mp_find_impl, V> { using type = mp_size_t<0>; }; #if defined( BOOST_MP11_HAS_CXX14_CONSTEXPR ) constexpr std::size_t cx_find_index( bool const * first, bool const * last ) { std::size_t m = 0; while( first != last && !*first ) { ++m; ++first; } return m; } #else constexpr std::size_t cx_find_index( bool const * first, bool const * last ) { return first == last || *first? 0: 1 + cx_find_index( first + 1, last ); } #endif template class L, class... T, class V> struct mp_find_impl, V> { static constexpr bool _v[] = { std::is_same::value... }; using type = mp_size_t< cx_find_index( _v, _v + sizeof...(T) ) >; }; #else #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) template class L, class... T, class V> struct mp_find_impl, V> { static_assert( sizeof...(T) == 0, "T... must be empty" ); using type = mp_size_t<0>; }; #else template class L, class V> struct mp_find_impl, V> { using type = mp_size_t<0>; }; #endif template class L, class... T, class V> struct mp_find_impl, V> { using type = mp_size_t<0>; }; template class L, class T1, class... T, class V> struct mp_find_impl, V> { using _r = typename mp_find_impl, V>::type; using type = mp_size_t<1 + _r::value>; }; #endif } // namespace detail template using mp_find = typename detail::mp_find_impl::type; // mp_find_if namespace detail { template class P> struct mp_find_if_impl; #if BOOST_MP11_CLANG && defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) template class L, class... T, template class P> struct mp_find_if_impl, P> { static constexpr mp_index_holder _v{ 0, false }; using type = mp_size_t< (_v + ... + P::value).i_ >; }; #elif !defined( BOOST_MP11_NO_CONSTEXPR ) template class L, template class P> struct mp_find_if_impl, P> { using type = mp_size_t<0>; }; template class L, class... T, template class P> struct mp_find_if_impl, P> { static constexpr bool _v[] = { P::value... }; using type = mp_size_t< cx_find_index( _v, _v + sizeof...(T) ) >; }; #else #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) template class L, class... T, template class P> struct mp_find_if_impl, P> { static_assert( sizeof...(T) == 0, "T... must be empty" ); using type = mp_size_t<0>; }; #else template class L, template class P> struct mp_find_if_impl, P> { using type = mp_size_t<0>; }; #endif 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, class T1, class... T, template class P> struct mp_find_if_impl, P> { using type = typename mp_if, mp_identity>, mp_find_if_impl_2, P>>::type; }; #endif } // namespace detail template class P> using mp_find_if = typename detail::mp_find_if_impl::type; template using mp_find_if_q = mp_find_if; // mp_reverse namespace detail { template struct mp_reverse_impl; #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) template class L, class... T> struct mp_reverse_impl> { static_assert( sizeof...(T) == 0, "T... must be empty" ); using type = L<>; }; #else template class L> struct mp_reverse_impl> { using type = L<>; }; #endif template class L, class T1> struct mp_reverse_impl> { using type = L; }; template class L, class T1, class T2> struct mp_reverse_impl> { using type = L; }; template class L, class T1, class T2, class T3> struct mp_reverse_impl> { using type = L; }; template class L, class T1, class T2, class T3, class T4> struct mp_reverse_impl> { using type = L; }; template class L, class T1, class T2, class T3, class T4, class T5> struct mp_reverse_impl> { using type = L; }; template class L, class T1, class T2, class T3, class T4, class T5, class T6> struct mp_reverse_impl> { using type = L; }; template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7> struct mp_reverse_impl> { using type = L; }; template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8> struct mp_reverse_impl> { using type = L; }; template class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9> struct mp_reverse_impl> { using type = L; }; template 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> { using type = mp_push_back>::type, T10, T9, T8, T7, T6, T5, T4, T3, T2, T1>; }; } // namespace detail template using mp_reverse = typename detail::mp_reverse_impl::type; // mp_fold // in detail/mp_fold.hpp // mp_reverse_fold namespace detail { template class F> struct mp_reverse_fold_impl; #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) template class L, class... T, class V, template class F> struct mp_reverse_fold_impl, V, F> { static_assert( sizeof...(T) == 0, "T... must be empty" ); using type = V; }; #else template class L, class V, template class F> struct mp_reverse_fold_impl, V, F> { using type = V; }; #endif template class L, class T1, class... T, class V, template class F> struct mp_reverse_fold_impl, V, F> { using rest = typename mp_reverse_fold_impl, V, F>::type; using type = F; }; template 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 F> struct mp_reverse_fold_impl, V, F> { using rest = typename mp_reverse_fold_impl, V, F>::type; using type = F > > > > > > > > >; }; } // namespace detail template class F> using mp_reverse_fold = typename detail::mp_reverse_fold_impl::type; template using mp_reverse_fold_q = mp_reverse_fold; // mp_unique namespace detail { template struct mp_unique_impl; template class L, class... T> struct mp_unique_impl> { using type = mp_set_push_back, T...>; }; } // namespace detail template using mp_unique = typename detail::mp_unique_impl::type; // mp_all_of template class P> using mp_all_of = mp_bool< mp_count_if::value == mp_size::value >; template using mp_all_of_q = mp_all_of; // mp_none_of template class P> using mp_none_of = mp_bool< mp_count_if::value == 0 >; template using mp_none_of_q = mp_none_of; // mp_any_of template class P> using mp_any_of = mp_bool< mp_count_if::value != 0 >; template using mp_any_of_q = mp_any_of; // mp_replace_at_c namespace detail { template struct mp_replace_at_impl { static_assert( I::value >= 0, "mp_replace_at: I must not be negative" ); template using _p = std::is_same>; template using _f = W; using type = mp_transform_if<_p, _f, L, mp_iota > >; }; } // namespace detail template using mp_replace_at = typename detail::mp_replace_at_impl::type; template using mp_replace_at_c = typename detail::mp_replace_at_impl, W>::type; //mp_for_each(f) namespace detail { template BOOST_MP11_CONSTEXPR F mp_for_each_impl( mp_list, F && f ) { using A = int[sizeof...(T)]; return (void)A{ ((void)f(T()), 0)... }, std::forward(f); } template BOOST_MP11_CONSTEXPR F mp_for_each_impl( mp_list<>, F && f ) { return std::forward(f); } } // namespace detail #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, >= 1900 ) // msvc has a limit of 1024 template BOOST_MP11_CONSTEXPR mp_if_c::value <= 1024, F> mp_for_each( F && f ) { return detail::mp_for_each_impl( mp_rename(), std::forward(f) ); } template BOOST_MP11_CONSTEXPR mp_if_c::value >= 1025, F> mp_for_each( F && f ) { using L2 = mp_rename; using L3 = mp_take_c; using L4 = mp_drop_c; return mp_for_each( mp_for_each( std::forward(f) ) ); } #else template BOOST_MP11_CONSTEXPR F mp_for_each( F && f ) { return detail::mp_for_each_impl( mp_rename(), std::forward(f) ); } #endif // mp_insert template using mp_insert = mp_append, mp_push_front, T...>>; // mp_insert_c template using mp_insert_c = mp_append, mp_push_front, T...>>; // mp_erase template using mp_erase = mp_append, mp_drop>; // mp_erase_c template using mp_erase_c = mp_append, mp_drop_c>; // mp_starts_with // contributed by Glen Joseph Fernandes (glenjofe@gmail.com) namespace detail { template struct mp_starts_with_impl { }; template class L1, class... T1, template class L2, class... T2> struct mp_starts_with_impl, L2 > { template static mp_false check(L); template static mp_true check(mp_list); using type = decltype(check(mp_list())); }; } // namespace detail template using mp_starts_with = typename detail::mp_starts_with_impl::type; // mp_min_element // mp_max_element // in detail/mp_min_element.hpp } // namespace mp11 } // namespace boost #endif // #ifndef BOOST_MP11_ALGORITHM_HPP_INCLUDED