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"
2017-03-18 19:48:07 +02:00
# if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 )
2017-04-01 18:08:19 +03:00
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 ;
2017-03-18 19:48:07 +02:00
# else
2017-04-01 18:08:19 +03:00
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 . . . > ;
2017-03-18 19:48:07 +02:00
# endif
2017-04-01 18:08:19 +03:00
using type = mp_transform < _f , L . . . > ;
2017-03-18 19:48:07 +02:00
} ;
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 ;
// 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
2015-06-22 03:37:15 +03:00
2017-03-25 20:32:40 +02:00
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 > > > ;
2015-06-22 03:37:15 +03:00
} ;
2017-03-25 20:32:40 +02:00
# endif
2015-06-22 03:37:15 +03:00
2017-03-25 20:32:40 +02:00
} // namespace detail
2015-06-22 03:37:15 +03:00
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 >
2015-06-22 03:37:15 +03:00
{
2017-03-22 02:03:39 +02:00
using type = L < > ;
} ;
2015-06-22 03:37:15 +03:00
2017-03-22 02:03:39 +02:00
template < template < class . . . > class L , class T1 , class . . . T > struct mp_take_c_impl < L < T1 , T . . . > , 1 >
{
using type = L < T1 > ;
} ;
2015-06-22 03:37:15 +03:00
2017-03-22 02:03:39 +02:00
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 > ;
} ;
2015-06-22 03:37:15 +03:00
2017-03-22 02:03:39 +02:00
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 > ;
} ;
2015-06-22 03:37:15 +03:00
2017-03-22 02:03:39 +02:00
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 > ;
2015-06-22 03:37:15 +03:00
} ;
2017-03-22 02:03:39 +02:00
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 > ;
} ;
} // namespace detail
2015-06-22 03:37:15 +03:00
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 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-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