2015-06-21 20:47:04 +03:00
#ifndef BOOST_MP11_ALGORITHM_HPP_INCLUDED
#define BOOST_MP11_ALGORITHM_HPP_INCLUDED
2017-03-14 16:32:17 +02:00
// Copyright 2015-2017 Peter Dimov.
2015-06-21 20:47:04 +03:00
//
// 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 <boost/mp11/list.hpp>
2015-07-24 13:45:08 +03:00
#include <boost/mp11/set.hpp>
2015-06-21 20:47:04 +03:00
#include <boost/mp11/integral.hpp>
2015-06-22 02:42:37 +03:00
#include <boost/mp11/utility.hpp>
2016-11-16 21:24:13 +02:00
#include <boost/mp11/detail/mp_count.hpp>
2016-11-16 19:55:35 +02:00
#include <boost/mp11/detail/mp_plus.hpp>
2015-06-22 03:37:15 +03:00
#include <boost/mp11/detail/mp_map_find.hpp>
2016-10-23 18:16:55 +03:00
#include <boost/mp11/detail/config.hpp>
2015-06-22 03:37:15 +03:00
#include <boost/integer_sequence.hpp>
2015-06-21 20:47:04 +03:00
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <type_traits>
2017-05-13 00:10:50 +03:00
#include <utility>
2015-06-21 20:47:04 +03:00
namespace boost
{
2017-03-15 21:23:15 +02:00
namespace mp11
{
2015-06-21 20:47:04 +03:00
// mp_assign<L1, L2>
namespace detail
{
template < class L1 , class L2 > struct mp_assign_impl ;
template < template < class ... > class L1 , class ... T , template < class ... > class L2 , class ... U > struct mp_assign_impl < L1 < T ... > , L2 < U ... >>
{
using type = L1 < U ... > ;
};
} // namespace detail
template < class L1 , class L2 > using mp_assign = typename detail :: mp_assign_impl < L1 , L2 >:: type ;
// mp_clear<L>
template < class L > using mp_clear = mp_assign < L , mp_list <>> ;
2017-04-01 17:39:02 +03:00
// mp_fold<L, V, F> forward declaration
namespace detail
{
template < class L , class V , template < class ... > class F > struct mp_fold_impl ;
} // namespace detail
template < class L , class V , template < class ... > class F > using mp_fold = typename detail :: mp_fold_impl < L , V , F >:: type ;
2015-06-21 20:47:04 +03:00
// mp_transform<F, L...>
namespace detail
{
template < template < class ... > class F , class ... L > struct mp_transform_impl ;
template < template < class ... > class F , template < class ... > class L , class ... T > struct mp_transform_impl < F , L < T ... >>
{
using type = L < F < T > ... > ;
};
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 ... >>
{
static_assert ( sizeof ...( T1 ) == sizeof ...( T2 ), "The arguments of mp_transform should be of the same size" );
using type = L1 < F < T1 , T2 > ... > ;
};
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 ... >>
{
static_assert ( sizeof ...( T1 ) == sizeof ...( T2 ) && sizeof ...( T1 ) == sizeof ...( T3 ), "The arguments of mp_transform should be of the same size" );
using type = L1 < F < T1 , T2 , T3 > ... > ;
};
} // namespace detail
template < template < class ... > class F , class ... L > using mp_transform = typename detail :: mp_transform_impl < F , L ... >:: type ;
2017-05-09 20:53:00 +03:00
template < class Q , class ... L > using mp_transform_q = mp_transform < Q :: template fn , L ... > ;
2015-06-21 20:47:04 +03:00
2017-04-01 17:39:02 +03:00
namespace detail
{
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 ... >
{
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 < mp_list < T1 , T2 , T3 , T4 > ... > ;
template < class V , class T > using _f = mp_transform < mp_push_back , V , T > ;
using A2 = mp_fold < mp_list < L ... > , A1 , _f > ;
template < class T > using _g = mp_apply < F , T > ;
using type = mp_transform < _g , A2 > ;
};
} // namespace detail
2017-03-18 19:48:07 +02:00
// mp_transform_if<P, F, L...>
2017-03-14 16:32:17 +02:00
namespace detail
{
2017-03-18 19:48:07 +02:00
template < template < class ... > class P , template < class ... > class F , class ... L > struct mp_transform_if_impl
{
2017-04-01 18:08:19 +03:00
// 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 < class ... U > struct _f_ { using type = mp_eval_if < mp_not < mp_invoke < mp_quote < P > , U ... >> , mp_first < mp_list < U ... >> , mp_quote < F >:: template fn , U ... > ; };
template < class ... U > using _f = typename _f_ < U ... >:: type ;
#else
template < class ... U > using _f = mp_eval_if < mp_not < mp_invoke < mp_quote < P > , U ... >> , mp_first < mp_list < U ... >> , mp_quote < F >:: template fn , U ... > ;
#endif
2017-03-18 19:48:07 +02:00
using type = mp_transform < _f , L ... > ;
};
2017-03-14 16:32:17 +02:00
} // namespace detail
2017-03-18 19:48:07 +02:00
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 ;
2017-03-14 16:32:17 +02:00
2015-06-21 20:47:04 +03:00
// mp_fill<L, V>
namespace detail
{
template < class L , class V > struct mp_fill_impl ;
template < template < class ... > class L , class ... T , class V > struct mp_fill_impl < L < T ... > , V >
{
2015-07-23 18:35:25 +03:00
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1900 )
2015-06-21 20:47:04 +03:00
template < class ... > struct _f { using type = V ; };
using type = L < typename _f < T >:: type ... > ;
#else
template < class ... > using _f = V ;
using type = L < _f < T > ... > ;
#endif
};
} // namespace detail
template < class L , class V > using mp_fill = typename detail :: mp_fill_impl < L , V >:: type ;
// mp_contains<L, V>
template < class L , class V > using mp_contains = mp_to_bool < mp_count < L , V >> ;
// mp_repeat(_c)<L, N>
namespace detail
{
template < class L , std :: size_t N > struct mp_repeat_c_impl
{
using _l1 = typename mp_repeat_c_impl < L , N / 2 >:: type ;
using _l2 = typename mp_repeat_c_impl < L , N % 2 >:: type ;
using type = mp_append < _l1 , _l1 , _l2 > ;
};
template < class L > struct mp_repeat_c_impl < L , 0 >
{
using type = mp_clear < L > ;
};
template < class L > struct mp_repeat_c_impl < L , 1 >
{
using type = L ;
};
} // namespace detail
template < class L , std :: size_t N > using mp_repeat_c = typename detail :: mp_repeat_c_impl < L , N >:: type ;
2017-03-24 19:00:52 +02:00
template < class L , class N > using mp_repeat = typename detail :: mp_repeat_c_impl < L , std :: size_t { N :: value } >:: type ;
2015-06-21 20:47:04 +03:00
2015-06-22 00:46:24 +03:00
// mp_product<F, L...>
namespace detail
{
template < template < class ... > class F , class P , class ... L > struct mp_product_impl_2 ;
template < template < class ... > class F , class P > struct mp_product_impl_2 < F , P >
{
using type = mp_list < mp_rename < P , F >> ;
};
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 ... >
{
using type = mp_append < typename mp_product_impl_2 < F , mp_push_back < P , T1 > , L ... >:: type ... > ;
};
template < template < class ... > class F , class ... L > struct mp_product_impl ;
template < template < class ... > class F , class L1 , class ... L > struct mp_product_impl < F , L1 , L ... >
{
using type = mp_assign < L1 , typename mp_product_impl_2 < F , mp_list <> , L1 , L ... >:: type > ;
};
} // namespace detail
template < template < class ... > class F , class ... L > using mp_product = typename detail :: mp_product_impl < F , L ... >:: type ;
2017-05-13 21:07:54 +03:00
template < class Q , class ... L > using mp_product_q = typename detail :: mp_product_impl < Q :: template fn , L ... >:: type ;
2015-06-22 00:46:24 +03:00
// mp_drop(_c)<L, N>
2015-06-22 02:42:37 +03:00
namespace detail
{
template < class L , class L2 > struct mp_drop_impl ;
template < template < class ... > class L , class ... T , template < class ... > class L2 , class ... U > struct mp_drop_impl < L < T ... > , L2 < U ... >>
{
template < class ... W > static mp_identity < L < W ... >> f ( U * ..., mp_identity < W >* ... );
using R = decltype ( f ( ( mp_identity < T >* ) 0 ... ) );
using type = typename R :: type ;
};
} // namespace detail
template < class L , std :: size_t N > using mp_drop_c = typename detail :: mp_drop_impl < L , mp_repeat_c < mp_list < void > , N >>:: type ;
template < class L , class N > using mp_drop = typename detail :: mp_drop_impl < L , mp_repeat < mp_list < void > , N >>:: type ;
2015-06-22 03:37:15 +03:00
// mp_iota(_c)<N>
namespace detail
{
template < class S > struct mp_from_sequence_impl ;
template < template < class T , T ... I > class S , class U , U ... J > struct mp_from_sequence_impl < S < U , J ... >>
{
using type = mp_list < std :: integral_constant < U , J > ... > ;
};
template < class S > using mp_from_sequence = typename mp_from_sequence_impl < S >:: type ;
} // namespace detail
template < std :: size_t N > using mp_iota_c = detail :: mp_from_sequence < make_index_sequence < N >> ;
template < class N > using mp_iota = detail :: mp_from_sequence < make_integer_sequence < typename std :: remove_const < decltype ( N :: value ) >:: type , N :: value >> ;
2015-06-22 00:46:24 +03:00
// mp_at(_c)<L, I>
2015-06-22 03:37:15 +03:00
namespace detail
{
2017-03-25 20:32:40 +02:00
template < class L , std :: size_t I > struct mp_at_c_impl ;
#if defined(BOOST_MP11_HAS_TYPE_PACK_ELEMENT)
template < template < class ... > class L , class ... T , std :: size_t I > struct mp_at_c_impl < L < T ... > , I >
2015-06-22 03:37:15 +03:00
{
2017-03-25 20:32:40 +02:00
using type = __type_pack_element < I , T ... > ;
2015-06-22 03:37:15 +03:00
};
2017-03-25 20:32:40 +02:00
#else
template < class L , std :: size_t I > struct mp_at_c_impl
{
using _map = mp_transform < mp_list , mp_iota < mp_size < L >> , L > ;
using type = mp_second < mp_map_find < _map , mp_size_t < I >>> ;
};
#endif
2015-06-22 03:37:15 +03:00
} // namespace detail
2017-03-25 20:32:40 +02:00
template < class L , std :: size_t I > using mp_at_c = typename detail :: mp_at_c_impl < L , I >:: type ;
template < class L , class I > using mp_at = typename detail :: mp_at_c_impl < L , std :: size_t { I :: value } >:: type ;
2015-06-22 03:37:15 +03:00
// mp_take(_c)<L, N>
namespace detail
{
2017-03-22 02:03:39 +02:00
template < class L , std :: size_t N , class E = void > struct mp_take_c_impl ;
template < template < class ... > class L , class ... T > struct mp_take_c_impl < L < T ... > , 0 >
{
using type = L <> ;
};
template < template < class ... > class L , class T1 , class ... T > struct mp_take_c_impl < L < T1 , T ... > , 1 >
{
using type = L < T1 > ;
};
template < template < class ... > class L , class T1 , class T2 , class ... T > struct mp_take_c_impl < L < T1 , T2 , T ... > , 2 >
{
using type = L < T1 , T2 > ;
};
template < template < class ... > class L , class T1 , class T2 , class T3 , class ... T > struct mp_take_c_impl < L < T1 , T2 , T3 , T ... > , 3 >
{
using type = L < T1 , T2 , T3 > ;
};
template < template < class ... > class L , class T1 , class T2 , class T3 , class T4 , class ... T > struct mp_take_c_impl < L < T1 , T2 , T3 , T4 , T ... > , 4 >
{
using type = L < T1 , T2 , T3 , T4 > ;
};
template < template < class ... > class L , class T1 , class T2 , class T3 , class T4 , class T5 , class ... T , std :: size_t N > struct mp_take_c_impl < L < T1 , T2 , T3 , T4 , T5 , T ... > , N , typename std :: enable_if < N >= 5 >:: type >
{
using type = mp_append < L < T1 , T2 , T3 , T4 , T5 > , typename mp_take_c_impl < L < T ... > , N - 5 >:: type > ;
};
2015-06-22 03:37:15 +03:00
} // namespace detail
2017-03-22 02:03:39 +02:00
template < class L , std :: size_t N > using mp_take_c = typename detail :: mp_take_c_impl < L , N >:: type ;
2017-03-24 19:12:13 +02:00
template < class L , class N > using mp_take = typename detail :: mp_take_c_impl < L , std :: size_t { N :: value } >:: type ;
2015-06-22 03:37:15 +03:00
2015-06-23 16:26:56 +03:00
// mp_replace<L, V, W>
namespace detail
{
template < class L , class V , class W > struct mp_replace_impl ;
template < template < class ... > class L , class ... T , class V , class W > struct mp_replace_impl < L < T ... > , V , W >
{
2017-03-24 18:47:55 +02:00
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
2015-06-23 16:26:56 +03:00
template < class A > struct _f { using type = mp_if < std :: is_same < A , V > , W , A > ; };
using type = L < typename _f < T >:: type ... > ;
#else
template < class A > using _f = mp_if < std :: is_same < A , V > , W , A > ;
2017-03-24 18:47:55 +02:00
using type = L < _f < T > ... > ;
2015-06-23 16:26:56 +03:00
#endif
2017-03-24 18:47:55 +02:00
};
2015-06-23 16:26:56 +03:00
} // namespace detail
template < class L , class V , class W > using mp_replace = typename detail :: mp_replace_impl < L , V , W >:: type ;
// mp_replace_if<L, P, W>
namespace detail
{
2017-03-24 18:47:55 +02:00
template < class L , template < class ... > class P , class W > struct mp_replace_if_impl ;
2015-06-23 16:26:56 +03:00
2017-03-24 18:47:55 +02:00
template < template < class ... > class L , class ... T , template < class ... > class P , class W > struct mp_replace_if_impl < L < T ... > , P , W >
{
template < class U > using _f = mp_if < P < U > , W , U > ;
using type = L < _f < T > ... > ;
2015-06-23 16:26:56 +03:00
};
} // namespace detail
template < class L , template < class ... > class P , class W > using mp_replace_if = typename detail :: mp_replace_if_impl < L , P , W >:: type ;
2015-06-24 16:05:47 +03:00
// mp_copy_if<L, P>
namespace detail
{
template < class L , template < class ... > class P > struct mp_copy_if_impl ;
template < template < class ... > class L , class ... T , template < class ... > class P > struct mp_copy_if_impl < L < T ... > , P >
{
2017-03-24 15:22:10 +02:00
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 )
template < class U > struct _f { using type = mp_if < P < U > , mp_list < U > , mp_list <>> ; };
using type = mp_append < L <> , typename _f < T >:: type ... > ;
2015-06-24 16:05:47 +03:00
#else
2017-03-24 15:22:10 +02:00
template < class U > using _f = mp_if < P < U > , mp_list < U > , mp_list <>> ;
using type = mp_append < L <> , _f < T > ... > ;
2015-06-24 16:05:47 +03:00
#endif
};
} // namespace detail
template < class L , template < class ... > class P > using mp_copy_if = typename detail :: mp_copy_if_impl < L , P >:: type ;
2015-07-24 01:17:16 +03:00
// mp_remove<L, V>
namespace detail
{
template < class L , class V > struct mp_remove_impl ;
template < template < class ... > class L , class ... T , class V > struct mp_remove_impl < L < T ... > , V >
{
2017-03-24 15:22:10 +02:00
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 )
template < class U > struct _f { using type = mp_if < std :: is_same < U , V > , mp_list <> , mp_list < U >> ; };
using type = mp_append < L <> , typename _f < T >:: type ... > ;
2015-07-24 01:17:16 +03:00
#else
2017-03-24 15:22:10 +02:00
template < class U > using _f = mp_if < std :: is_same < U , V > , mp_list <> , mp_list < U >> ;
using type = mp_append < L <> , _f < T > ... > ;
2015-07-24 01:17:16 +03:00
#endif
};
} // namespace detail
template < class L , class V > using mp_remove = typename detail :: mp_remove_impl < L , V >:: type ;
2015-06-24 16:05:47 +03:00
// mp_remove_if<L, P>
namespace detail
{
template < class L , template < class ... > class P > struct mp_remove_if_impl ;
template < template < class ... > class L , class ... T , template < class ... > class P > struct mp_remove_if_impl < L < T ... > , P >
{
2017-03-24 15:22:10 +02:00
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 )
template < class U > struct _f { using type = mp_if < P < U > , mp_list <> , mp_list < U >> ; };
using type = mp_append < L <> , typename _f < T >:: type ... > ;
2015-06-24 16:05:47 +03:00
#else
2017-03-24 15:22:10 +02:00
template < class U > using _f = mp_if < P < U > , mp_list <> , mp_list < U >> ;
using type = mp_append < L <> , _f < T > ... > ;
2015-06-24 16:05:47 +03:00
#endif
};
} // namespace detail
template < class L , template < class ... > class P > using mp_remove_if = typename detail :: mp_remove_if_impl < L , P >:: type ;
// mp_partition<L, P>
namespace detail
{
template < class L , template < class ... > class P > struct mp_partition_impl ;
template < template < class ... > class L , class ... T , template < class ... > class P > struct mp_partition_impl < L < T ... > , P >
{
2017-03-24 15:22:10 +02:00
using type = L < mp_copy_if < L < T ... > , P > , mp_remove_if < L < T ... > , P >> ;
2015-06-24 16:05:47 +03:00
};
} // namespace detail
template < class L , template < class ... > class P > using mp_partition = typename detail :: mp_partition_impl < L , P >:: type ;
// mp_sort<L, P>
namespace detail
{
template < class L , template < class ... > class P > struct mp_sort_impl ;
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
template < template < class ... > class L , class ... T , template < class ... > class P > struct mp_sort_impl < L < T ... > , P >
{
static_assert ( sizeof ...( T ) == 0 , "T... must be empty" );
using type = L <> ;
};
#else
template < template < class ... > class L , template < class ... > class P > struct mp_sort_impl < L <> , P >
{
using type = L <> ;
};
#endif
template < template < class ... > class L , class T1 , template < class ... > class P > struct mp_sort_impl < L < T1 > , P >
{
using type = L < T1 > ;
};
template < template < class ... > class L , class T1 , class ... T , template < class ... > class P > struct mp_sort_impl < L < T1 , T ... > , P >
{
template < class U > using F = P < U , T1 > ;
using part = mp_partition < L < T ... > , F > ;
using S1 = typename mp_sort_impl < mp_first < part > , P >:: type ;
using S2 = typename mp_sort_impl < mp_second < part > , P >:: type ;
using type = mp_append < mp_push_back < S1 , T1 > , S2 > ;
};
} // namespace detail
template < class L , template < class ... > class P > using mp_sort = typename detail :: mp_sort_impl < L , P >:: type ;
2017-03-15 20:03:56 +02:00
// mp_find<L, V>
2015-07-15 17:14:00 +03:00
namespace detail
{
2017-03-15 20:03:56 +02:00
template < class L , class V > struct mp_find_impl ;
2015-07-15 17:14:00 +03:00
2017-03-18 01:05:54 +02:00
#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 < template < class ... > class L , class ... T , class V > struct mp_find_impl < L < T ... > , V >
{
static constexpr mp_index_holder _v { 0 , false };
using type = mp_size_t < ( _v + ... + std :: is_same < T , V >:: value ). i_ > ;
};
#elif !defined( BOOST_MP11_NO_CONSTEXPR )
2015-07-15 17:14:00 +03:00
2017-03-15 20:03:56 +02:00
template < template < class ... > class L , class V > struct mp_find_impl < L <> , V >
2015-07-15 17:14:00 +03:00
{
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 );
}
2017-03-15 20:03:56 +02:00
template < template < class ... > class L , class ... T , class V > struct mp_find_impl < L < T ... > , V >
2015-07-15 17:14:00 +03:00
{
static constexpr bool _v [] = { std :: is_same < T , V >:: value ... };
using type = mp_size_t < cx_find_index ( _v , _v + sizeof ...( T ) ) > ;
};
#else
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
2017-03-15 20:03:56 +02:00
template < template < class ... > class L , class ... T , class V > struct mp_find_impl < L < T ... > , V >
2015-07-15 17:14:00 +03:00
{
static_assert ( sizeof ...( T ) == 0 , "T... must be empty" );
using type = mp_size_t < 0 > ;
};
#else
2017-03-15 20:03:56 +02:00
template < template < class ... > class L , class V > struct mp_find_impl < L <> , V >
2015-07-15 17:14:00 +03:00
{
using type = mp_size_t < 0 > ;
};
#endif
2017-03-15 20:03:56 +02:00
template < template < class ... > class L , class ... T , class V > struct mp_find_impl < L < V , T ... > , V >
2015-07-15 17:14:00 +03:00
{
using type = mp_size_t < 0 > ;
};
2017-03-15 20:03:56 +02:00
template < template < class ... > class L , class T1 , class ... T , class V > struct mp_find_impl < L < T1 , T ... > , V >
2015-07-15 17:14:00 +03:00
{
2017-03-15 20:03:56 +02:00
using _r = typename mp_find_impl < mp_list < T ... > , V >:: type ;
2015-07-15 17:14:00 +03:00
using type = mp_size_t < 1 + _r :: value > ;
};
#endif
} // namespace detail
2017-03-15 20:03:56 +02:00
template < class L , class V > using mp_find = typename detail :: mp_find_impl < L , V >:: type ;
2015-07-15 17:14:00 +03:00
2017-03-15 20:03:56 +02:00
// mp_find_if<L, P>
2015-07-15 17:30:07 +03:00
namespace detail
{
2017-03-15 20:03:56 +02:00
template < class L , template < class ... > class P > struct mp_find_if_impl ;
2015-07-15 17:30:07 +03:00
2017-03-18 01:05:54 +02:00
#if defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS )
template < template < class ... > class L , class ... T , template < class ... > class P > struct mp_find_if_impl < L < T ... > , P >
{
static constexpr mp_index_holder _v { 0 , false };
using type = mp_size_t < ( _v + ... + P < T >:: value ). i_ > ;
};
#elif !defined( BOOST_MP11_NO_CONSTEXPR )
2015-07-15 17:30:07 +03:00
2017-03-15 20:03:56 +02:00
template < template < class ... > class L , template < class ... > class P > struct mp_find_if_impl < L <> , P >
2015-07-15 17:30:07 +03:00
{
using type = mp_size_t < 0 > ;
};
2017-03-15 20:03:56 +02:00
template < template < class ... > class L , class ... T , template < class ... > class P > struct mp_find_if_impl < L < T ... > , P >
2015-07-15 17:30:07 +03:00
{
static constexpr bool _v [] = { P < T >:: value ... };
using type = mp_size_t < cx_find_index ( _v , _v + sizeof ...( T ) ) > ;
};
#else
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
2017-03-15 20:03:56 +02:00
template < template < class ... > class L , class ... T , template < class ... > class P > struct mp_find_if_impl < L < T ... > , P >
2015-07-15 17:30:07 +03:00
{
static_assert ( sizeof ...( T ) == 0 , "T... must be empty" );
using type = mp_size_t < 0 > ;
};
#else
2017-03-15 20:03:56 +02:00
template < template < class ... > class L , template < class ... > class P > struct mp_find_if_impl < L <> , P >
2015-07-15 17:30:07 +03:00
{
using type = mp_size_t < 0 > ;
};
#endif
2017-03-15 20:03:56 +02:00
template < class L , template < class ... > class P > struct mp_find_if_impl_2
2015-07-15 17:30:07 +03:00
{
2017-03-15 20:03:56 +02:00
using _r = typename mp_find_if_impl < L , P >:: type ;
2015-07-15 17:30:07 +03:00
using type = mp_size_t < 1 + _r :: value > ;
};
2017-03-15 20:03:56 +02:00
template < template < class ... > class L , class T1 , class ... T , template < class ... > class P > struct mp_find_if_impl < L < T1 , T ... > , P >
2015-07-15 17:30:07 +03:00
{
2017-03-15 20:03:56 +02:00
using type = typename mp_if < P < T1 > , mp_identity < mp_size_t < 0 >> , mp_find_if_impl_2 < mp_list < T ... > , P >>:: type ;
2015-07-15 17:30:07 +03:00
};
#endif
} // namespace detail
2017-03-15 20:03:56 +02:00
template < class L , template < class ... > class P > using mp_find_if = typename detail :: mp_find_if_impl < L , P >:: type ;
2015-07-15 17:14:00 +03:00
2015-06-21 20:47:04 +03:00
// mp_reverse<L>
2015-07-24 01:17:16 +03:00
namespace detail
{
template < class L > struct mp_reverse_impl ;
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
template < template < class ... > class L , class ... T > struct mp_reverse_impl < L < T ... >>
{
static_assert ( sizeof ...( T ) == 0 , "T... must be empty" );
using type = L <> ;
};
#else
template < template < class ... > class L > struct mp_reverse_impl < L <>>
{
using type = L <> ;
};
#endif
template < template < class ... > class L , class T1 > struct mp_reverse_impl < L < T1 >>
{
using type = L < T1 > ;
};
template < template < class ... > class L , class T1 , class T2 > struct mp_reverse_impl < L < T1 , T2 >>
{
using type = L < T2 , T1 > ;
};
template < template < class ... > class L , class T1 , class T2 , class T3 > struct mp_reverse_impl < L < T1 , T2 , T3 >>
{
using type = L < T3 , T2 , T1 > ;
};
template < template < class ... > class L , class T1 , class T2 , class T3 , class T4 > struct mp_reverse_impl < L < T1 , T2 , T3 , T4 >>
{
using type = L < T4 , T3 , T2 , T1 > ;
};
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 >>
{
using type = L < T5 , T4 , T3 , T2 , T1 > ;
};
2017-03-24 16:55:06 +02:00
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 >>
2015-07-24 01:17:16 +03:00
{
2017-03-24 16:55:06 +02:00
using type = L < T6 , T5 , T4 , T3 , T2 , T1 > ;
};
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 >>
{
using type = L < T7 , T6 , T5 , T4 , T3 , T2 , T1 > ;
};
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 >>
{
using type = L < T8 , T7 , T6 , T5 , T4 , T3 , T2 , T1 > ;
};
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 >>
{
using type = L < T9 , T8 , T7 , T6 , T5 , T4 , T3 , T2 , T1 > ;
};
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 ... >>
{
using type = mp_push_back < typename mp_reverse_impl < L < T ... >>:: type , T10 , T9 , T8 , T7 , T6 , T5 , T4 , T3 , T2 , T1 > ;
2015-07-24 01:17:16 +03:00
};
} // namespace detail
template < class L > using mp_reverse = typename detail :: mp_reverse_impl < L >:: type ;
2015-06-21 20:47:04 +03:00
// mp_fold<L, V, F>
2015-07-24 02:11:40 +03:00
namespace detail
{
template < class L , class V , template < class ... > class F > struct mp_fold_impl ;
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
template < template < class ... > class L , class ... T , class V , template < class ... > class F > struct mp_fold_impl < L < T ... > , V , F >
{
static_assert ( sizeof ...( T ) == 0 , "T... must be empty" );
using type = V ;
};
#else
template < template < class ... > class L , class V , template < class ... > class F > struct mp_fold_impl < L <> , V , F >
{
using type = V ;
};
#endif
template < template < class ... > class L , class T1 , class ... T , class V , template < class ... > class F > struct mp_fold_impl < L < T1 , T ... > , V , F >
{
using type = typename mp_fold_impl < L < T ... > , F < V , T1 > , F >:: type ;
};
2017-03-24 17:21:38 +02:00
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_fold_impl < L < T1 , T2 , T3 , T4 , T5 , T6 , T7 , T8 , T9 , T10 , T ... > , V , F >
{
using type = typename mp_fold_impl < L < T ... > , F < F < F < F < F < F < F < F < F < F < V , T1 > , T2 > , T3 > , T4 > , T5 > , T6 > , T7 > , T8 > , T9 > , T10 > , F >:: type ;
};
2015-07-24 02:11:40 +03:00
} // namespace detail
2015-06-21 20:47:04 +03:00
// mp_reverse_fold<L, V, F>
2015-07-24 02:11:40 +03:00
namespace detail
{
template < class L , class V , template < class ... > class F > struct mp_reverse_fold_impl ;
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
template < template < class ... > class L , class ... T , class V , template < class ... > class F > struct mp_reverse_fold_impl < L < T ... > , V , F >
{
static_assert ( sizeof ...( T ) == 0 , "T... must be empty" );
using type = V ;
};
#else
template < template < class ... > class L , class V , template < class ... > class F > struct mp_reverse_fold_impl < L <> , V , F >
{
using type = V ;
};
#endif
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 >
{
using rest = typename mp_reverse_fold_impl < L < T ... > , V , F >:: type ;
using type = F < T1 , rest > ;
};
2017-03-24 18:10:07 +02:00
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 >
{
using rest = typename mp_reverse_fold_impl < L < T ... > , V , F >:: type ;
using type = F < T1 , F < T2 , F < T3 , F < T4 , F < T5 , F < T6 , F < T7 , F < T8 , F < T9 , F < T10 , rest >>>>>>>>>> ;
};
2015-07-24 02:11:40 +03:00
} // namespace detail
template < class L , class V , template < class ... > class F > using mp_reverse_fold = typename detail :: mp_reverse_fold_impl < L , V , F >:: type ;
2015-07-16 18:12:06 +03:00
// mp_unique<L>
2015-07-24 13:45:08 +03:00
namespace detail
{
template < class L > struct mp_unique_impl ;
template < template < class ... > class L , class ... T > struct mp_unique_impl < L < T ... >>
{
using type = mp_set_push_back < L <> , T ... > ;
};
} // namespace detail
template < class L > using mp_unique = typename detail :: mp_unique_impl < L >:: type ;
2015-06-21 20:47:04 +03:00
2015-07-24 13:54:30 +03:00
// mp_all_of<L, P>
2016-11-16 19:55:35 +02:00
template < class L , template < class ... > class P > using mp_all_of = mp_bool < mp_count_if < L , P >:: value == mp_size < L >:: value > ;
2016-11-16 04:19:37 +02:00
2015-07-24 13:54:30 +03:00
// mp_none_of<L, P>
2016-11-16 19:55:35 +02:00
template < class L , template < class ... > class P > using mp_none_of = mp_bool < mp_count_if < L , P >:: value == 0 > ;
2016-11-16 04:19:37 +02:00
2015-07-24 13:54:30 +03:00
// mp_any_of<L, P>
2016-11-16 19:55:35 +02:00
template < class L , template < class ... > class P > using mp_any_of = mp_bool < mp_count_if < L , P >:: value != 0 > ;
2015-07-24 13:54:30 +03:00
2017-03-18 20:20:31 +02:00
// mp_replace_at_c<L, I, W>
namespace detail
{
template < class L , class I , class W > struct mp_replace_at_impl
{
static_assert ( I :: value >= 0 , "mp_replace_at<L, I, W>: I must not be negative" );
template < class T1 , class T2 > using _p = std :: is_same < T2 , mp_size_t < I :: value >> ;
template < class T1 , class T2 > using _f = W ;
using type = mp_transform_if < _p , _f , L , mp_iota < mp_size < L >>> ;
};
} // namespace detail
template < class L , class I , class W > using mp_replace_at = typename detail :: mp_replace_at_impl < L , I , W >:: type ;
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 ;
2017-05-13 21:52:56 +03:00
//mp_for_each<L>(f)
2017-05-13 00:10:50 +03:00
namespace detail
{
template < class ... T , class F > BOOST_CONSTEXPR F mp_for_each_impl ( mp_list < T ... > , F && f )
{
using A = int [ sizeof ...( T )];
return ( void ) A { (( void ) f ( mp_identity < T > ()), 0 )... }, std :: forward < F > ( f );
}
#if BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
template < class F > BOOST_CONSTEXPR F mp_for_each_impl ( mp_list <> , F && f )
{
return std :: forward < F > ( f );
}
#endif
} // namespace detail
template < class L , class F > BOOST_CONSTEXPR F mp_for_each ( F && f )
{
return detail :: mp_for_each_impl ( mp_rename < L , mp_list > (), std :: forward < F > ( f ) );
}
2017-05-13 21:52:56 +03:00
// mp_insert<L, I, T...>
template < class L , class I , class ... T > using mp_insert = mp_append < mp_take < L , I > , mp_push_front < mp_drop < L , I > , T ... >> ;
// mp_insert_c<L, I, T...>
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 ... >> ;
// mp_erase<L, I, J>
template < class L , class I , class J > using mp_erase = mp_append < mp_take < L , I > , mp_drop < L , J >> ;
// mp_erase_c<L, I, J>
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 >> ;
2017-03-15 21:23:15 +02:00
} // namespace mp11
2015-06-21 20:47:04 +03:00
} // namespace boost
#endif // #ifndef BOOST_MP11_ALGORITHM_HPP_INCLUDED