#ifndef BOOST_MP11_ALGORITHM_HPP_INCLUDED #define BOOST_MP11_ALGORITHM_HPP_INCLUDED // Copyright 2015-2017 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 namespace boost { namespace mp11 { // mp_assign namespace detail { template struct mp_assign_impl; template class L1, class... T, template class L2, class... U> struct mp_assign_impl, L2> { using type = L1; }; } // namespace detail template using mp_assign = typename detail::mp_assign_impl::type; // mp_clear template using mp_clear = mp_assign>; // mp_fold forward declaration namespace detail { template class F> struct mp_fold_impl; } // namespace detail template class F> using mp_fold = typename detail::mp_fold_impl::type; // 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> { using type = L...>; }; template class F, template class L1, class... T1, template class L2, class... T2> struct mp_transform_impl, L2> { static_assert( sizeof...(T1) == sizeof...(T2), "The arguments of mp_transform should be of the same size" ); using type = L1...>; }; template class F, template class L1, class... T1, template class L2, class... T2, template class L3, class... T3> struct mp_transform_impl, L2, L3> { static_assert( sizeof...(T1) == sizeof...(T2) && sizeof...(T1) == sizeof...(T3), "The arguments of mp_transform should be of the same size" ); using type = L1...>; }; } // namespace detail template class F, class... L> using mp_transform = typename detail::mp_transform_impl::type; 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...> { static_assert( sizeof...(T1) == sizeof...(T2) && sizeof...(T1) == sizeof...(T3) && sizeof...(T1) == sizeof...(T4), "The arguments of mp_transform should be of the same size" ); 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" #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) template struct _f_ { using type = mp_eval_if, U...>>, mp_first>, mp_quote::template fn, U...>; }; template using _f = typename _f_::type; #else template using _f = mp_eval_if, U...>>, mp_first>, mp_quote::template fn, 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; // mp_fill namespace detail { template struct mp_fill_impl; template class L, class... T, class V> struct mp_fill_impl, V> { #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_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; // 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_iota(_c) namespace detail { template struct mp_from_sequence_impl; template class S, class U, U... J> struct mp_from_sequence_impl> { using type = mp_list...>; }; template using mp_from_sequence = typename mp_from_sequence_impl::type; } // namespace detail template using mp_iota_c = detail::mp_from_sequence>; template using mp_iota = detail::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 } // namespace detail template using mp_at_c = typename detail::mp_at_c_impl::type; template using mp_at = typename detail::mp_at_c_impl::type; // mp_take(_c) namespace detail { template struct mp_take_c_impl; template class L, class... T> struct mp_take_c_impl, 0> { using type = L<>; }; template class L, class T1, class... T> struct mp_take_c_impl, 1> { using type = L; }; template class L, class T1, class T2, class... T> struct mp_take_c_impl, 2> { using type = L; }; template class L, class T1, class T2, class T3, class... T> struct mp_take_c_impl, 3> { using type = L; }; template class L, class T1, class T2, class T3, class T4, class... T> struct mp_take_c_impl, 4> { using type = L; }; template class L, class T1, class T2, class T3, class T4, class T5, class... T, std::size_t N> struct mp_take_c_impl, N, typename std::enable_if= 5>::type> { using type = mp_append, typename mp_take_c_impl, N-5>::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_replace namespace detail { template struct mp_replace_impl; template class L, class... T, class V, class W> struct mp_replace_impl, V, W> { #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_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> { template using _f = mp_if, W, U>; using type = L<_f...>; }; } // namespace detail template class P, class W> using mp_replace_if = typename detail::mp_replace_if_impl::type; // mp_copy_if namespace detail { template class P> struct mp_copy_if_impl; template class L, class... T, template class P> struct mp_copy_if_impl, P> { #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) 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 class P> using mp_copy_if = typename detail::mp_copy_if_impl::type; // mp_remove namespace detail { template struct mp_remove_impl; template class L, class... T, class V> struct mp_remove_impl, V> { #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) 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 namespace detail { template class P> struct mp_remove_if_impl; template class L, class... T, template class P> struct mp_remove_if_impl, P> { #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 ) 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 class P> using mp_remove_if = typename detail::mp_remove_if_impl::type; // 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; // mp_sort namespace detail { template class P> struct mp_sort_impl; #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_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; // mp_find namespace detail { template struct mp_find_impl; #if 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>; }; 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 ); } 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 defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_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 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 defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_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; // mp_reverse namespace detail { template struct mp_reverse_impl; #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_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 namespace detail { template class F> struct mp_fold_impl; #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 ) template class L, class... T, class V, template class F> struct mp_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_fold_impl, V, F> { using type = V; }; #endif template class L, class T1, class... T, class V, template class F> struct mp_fold_impl, V, F> { using type = typename mp_fold_impl, F, F>::type; }; 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_fold_impl, V, F> { using type = typename mp_fold_impl, F, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>, T10>, F>::type; }; } // namespace detail // mp_reverse_fold namespace detail { template class F> struct mp_reverse_fold_impl; #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_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; // 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 >; // mp_none_of template class P> using mp_none_of = mp_bool< mp_count_if::value == 0 >; // mp_any_of template class P> using mp_any_of = mp_bool< mp_count_if::value != 0 >; // 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; } // namespace mp11 } // namespace boost #endif // #ifndef BOOST_MP11_ALGORITHM_HPP_INCLUDED