1 | #ifndef BOOST_MP11_ALGORITHM_HPP_INCLUDED |
2 | #define BOOST_MP11_ALGORITHM_HPP_INCLUDED |
3 | |
4 | // Copyright 2015-2019 Peter Dimov |
5 | // |
6 | // Distributed under the Boost Software License, Version 1.0. |
7 | // |
8 | // See accompanying file LICENSE_1_0.txt or copy at |
9 | // http://www.boost.org/LICENSE_1_0.txt |
10 | |
11 | #include <boost/mp11/list.hpp> |
12 | #include <boost/mp11/set.hpp> |
13 | #include <boost/mp11/integral.hpp> |
14 | #include <boost/mp11/utility.hpp> |
15 | #include <boost/mp11/function.hpp> |
16 | #include <boost/mp11/detail/mp_count.hpp> |
17 | #include <boost/mp11/detail/mp_plus.hpp> |
18 | #include <boost/mp11/detail/mp_map_find.hpp> |
19 | #include <boost/mp11/detail/mp_with_index.hpp> |
20 | #include <boost/mp11/detail/mp_fold.hpp> |
21 | #include <boost/mp11/detail/mp_min_element.hpp> |
22 | #include <boost/mp11/detail/mp_copy_if.hpp> |
23 | #include <boost/mp11/detail/mp_remove_if.hpp> |
24 | #include <boost/mp11/detail/config.hpp> |
25 | #include <boost/mp11/integer_sequence.hpp> |
26 | #include <type_traits> |
27 | #include <utility> |
28 | |
29 | #if defined(_MSC_VER) || defined(__GNUC__) |
30 | # pragma push_macro( "I" ) |
31 | # undef I |
32 | #endif |
33 | |
34 | namespace boost |
35 | { |
36 | namespace mp11 |
37 | { |
38 | |
39 | // mp_transform<F, L...> |
40 | namespace detail |
41 | { |
42 | |
43 | template<template<class...> class F, class... L> struct mp_transform_impl |
44 | { |
45 | }; |
46 | |
47 | template<template<class...> class F, template<class...> class L, class... T> struct mp_transform_impl<F, L<T...>> |
48 | { |
49 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) |
50 | |
51 | template<class... U> struct f { using type = F<U...>; }; |
52 | |
53 | using type = L<typename f<T>::type...>; |
54 | |
55 | #else |
56 | |
57 | using type = L<F<T>...>; |
58 | |
59 | #endif |
60 | }; |
61 | |
62 | 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...>> |
63 | { |
64 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) |
65 | |
66 | template<class... U> struct f { using type = F<U...>; }; |
67 | |
68 | using type = L1<typename f<T1, T2>::type...>; |
69 | |
70 | #else |
71 | |
72 | using type = L1<F<T1,T2>...>; |
73 | |
74 | #endif |
75 | }; |
76 | |
77 | 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...>> |
78 | { |
79 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) |
80 | |
81 | template<class... U> struct f { using type = F<U...>; }; |
82 | |
83 | using type = L1<typename f<T1, T2, T3>::type...>; |
84 | |
85 | #else |
86 | |
87 | using type = L1<F<T1,T2,T3>...>; |
88 | |
89 | #endif |
90 | }; |
91 | |
92 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
93 | |
94 | template<template<class...> class F, template<auto...> class L, auto... A> struct mp_transform_impl<F, L<A...>> |
95 | { |
96 | using type = L< F< mp_value<A> >::value... >; |
97 | }; |
98 | |
99 | template<template<class...> class F, template<auto...> class L1, auto... A1, template<auto...> class L2, auto... A2> struct mp_transform_impl<F, L1<A1...>, L2<A2...>> |
100 | { |
101 | using type = L1< F< mp_value<A1>, mp_value<A2> >::value... >; |
102 | }; |
103 | |
104 | template<template<class...> class F, template<auto...> class L1, auto... A1, template<auto...> class L2, auto... A2, template<auto...> class L3, auto... A3> struct mp_transform_impl<F, L1<A1...>, L2<A2...>, L3<A3...>> |
105 | { |
106 | using type = L1< F< mp_value<A1>, mp_value<A2>, mp_value<A3> >::value... >; |
107 | }; |
108 | |
109 | #endif |
110 | |
111 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, == 1900 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 40800 ) |
112 | |
113 | template<class... L> using mp_same_size_1 = mp_same<mp_size<L>...>; |
114 | template<class... L> struct mp_same_size_2: mp_defer<mp_same_size_1, L...> {}; |
115 | |
116 | #endif |
117 | |
118 | struct list_size_mismatch |
119 | { |
120 | }; |
121 | |
122 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) |
123 | |
124 | template<template<class...> class F, class... L> struct mp_transform_cuda_workaround |
125 | { |
126 | using type = mp_if<mp_same<mp_size<L>...>, detail::mp_transform_impl<F, L...>, detail::list_size_mismatch>; |
127 | }; |
128 | |
129 | #endif |
130 | |
131 | } // namespace detail |
132 | |
133 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, == 1900 ) || BOOST_MP11_WORKAROUND( BOOST_MP11_GCC, < 40800 ) |
134 | |
135 | template<template<class...> class F, class... L> using mp_transform = typename mp_if<typename detail::mp_same_size_2<L...>::type, detail::mp_transform_impl<F, L...>, detail::list_size_mismatch>::type; |
136 | |
137 | #else |
138 | |
139 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) |
140 | |
141 | template<template<class...> class F, class... L> using mp_transform = typename detail::mp_transform_cuda_workaround< F, L...>::type::type; |
142 | |
143 | #else |
144 | |
145 | template<template<class...> class F, class... L> using mp_transform = typename mp_if<mp_same<mp_size<L>...>, detail::mp_transform_impl<F, L...>, detail::list_size_mismatch>::type; |
146 | |
147 | #endif |
148 | |
149 | #endif |
150 | |
151 | template<class Q, class... L> using mp_transform_q = mp_transform<Q::template fn, L...>; |
152 | |
153 | namespace detail |
154 | { |
155 | |
156 | 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...> |
157 | { |
158 | using A1 = L1<mp_list<T1, T2, T3, T4>...>; |
159 | |
160 | template<class V, class T> using _f = mp_transform<mp_push_back, V, T>; |
161 | |
162 | using A2 = mp_fold<mp_list<L...>, A1, _f>; |
163 | |
164 | template<class T> using _g = mp_apply<F, T>; |
165 | |
166 | using type = mp_transform<_g, A2>; |
167 | }; |
168 | |
169 | } // namespace detail |
170 | |
171 | // mp_transform_if<P, F, L...> |
172 | namespace detail |
173 | { |
174 | |
175 | template<template<class...> class P, template<class...> class F, class... L> struct mp_transform_if_impl |
176 | { |
177 | // the stupid quote-unquote dance avoids "pack expansion used as argument for non-pack parameter of alias template" |
178 | |
179 | using Qp = mp_quote<P>; |
180 | using Qf = mp_quote<F>; |
181 | |
182 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) |
183 | |
184 | template<class... U> struct _f_ { using type = mp_eval_if_q<mp_not<mp_invoke_q<Qp, U...>>, mp_first<mp_list<U...>>, Qf, U...>; }; |
185 | template<class... U> using _f = typename _f_<U...>::type; |
186 | |
187 | #else |
188 | |
189 | template<class... U> using _f = mp_eval_if_q<mp_not<mp_invoke_q<Qp, U...>>, mp_first<mp_list<U...>>, Qf, U...>; |
190 | |
191 | #endif |
192 | |
193 | using type = mp_transform<_f, L...>; |
194 | }; |
195 | |
196 | } // namespace detail |
197 | |
198 | 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; |
199 | template<class Qp, class Qf, class... L> using mp_transform_if_q = typename detail::mp_transform_if_impl<Qp::template fn, Qf::template fn, L...>::type; |
200 | |
201 | // mp_filter<P, L...> |
202 | namespace detail |
203 | { |
204 | |
205 | template<template<class...> class P, class L1, class... L> struct mp_filter_impl |
206 | { |
207 | using Qp = mp_quote<P>; |
208 | |
209 | template<class T1, class... T> using _f = mp_if< mp_invoke_q<Qp, T1, T...>, mp_list<T1>, mp_list<> >; |
210 | |
211 | using _t1 = mp_transform<_f, L1, L...>; |
212 | using _t2 = mp_apply<mp_append, _t1>; |
213 | |
214 | using type = mp_assign<L1, _t2>; |
215 | }; |
216 | |
217 | } // namespace detail |
218 | |
219 | template<template<class...> class P, class... L> using mp_filter = typename detail::mp_filter_impl<P, L...>::type; |
220 | template<class Q, class... L> using mp_filter_q = typename detail::mp_filter_impl<Q::template fn, L...>::type; |
221 | |
222 | // mp_fill<L, V> |
223 | namespace detail |
224 | { |
225 | |
226 | template<class L, class V> struct mp_fill_impl |
227 | { |
228 | // An error "no type named 'type'" here means that the L argument of mp_fill is not a list |
229 | }; |
230 | |
231 | template<template<class...> class L, class... T, class V> struct mp_fill_impl<L<T...>, V> |
232 | { |
233 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1900 ) |
234 | |
235 | template<class...> struct _f { using type = V; }; |
236 | using type = L<typename _f<T>::type...>; |
237 | |
238 | #else |
239 | |
240 | template<class...> using _f = V; |
241 | using type = L<_f<T>...>; |
242 | |
243 | #endif |
244 | }; |
245 | |
246 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
247 | |
248 | template<template<auto...> class L, auto... A, class V> struct mp_fill_impl<L<A...>, V> |
249 | { |
250 | using type = L<((void)A, V::value)...>; |
251 | }; |
252 | |
253 | #endif |
254 | |
255 | } // namespace detail |
256 | |
257 | template<class L, class V> using mp_fill = typename detail::mp_fill_impl<L, V>::type; |
258 | |
259 | // mp_contains<L, V> |
260 | template<class L, class V> using mp_contains = mp_to_bool<mp_count<L, V>>; |
261 | |
262 | // mp_repeat(_c)<L, N> |
263 | namespace detail |
264 | { |
265 | |
266 | template<class L, std::size_t N> struct mp_repeat_c_impl |
267 | { |
268 | using _l1 = typename mp_repeat_c_impl<L, N/2>::type; |
269 | using _l2 = typename mp_repeat_c_impl<L, N%2>::type; |
270 | |
271 | using type = mp_append<_l1, _l1, _l2>; |
272 | }; |
273 | |
274 | template<class L> struct mp_repeat_c_impl<L, 0> |
275 | { |
276 | using type = mp_clear<L>; |
277 | }; |
278 | |
279 | template<class L> struct mp_repeat_c_impl<L, 1> |
280 | { |
281 | using type = L; |
282 | }; |
283 | |
284 | } // namespace detail |
285 | |
286 | template<class L, std::size_t N> using mp_repeat_c = typename detail::mp_repeat_c_impl<L, N>::type; |
287 | template<class L, class N> using mp_repeat = typename detail::mp_repeat_c_impl<L, std::size_t{ N::value }>::type; |
288 | |
289 | // mp_product<F, L...> |
290 | namespace detail |
291 | { |
292 | |
293 | template<template<class...> class F, class P, class... L> struct mp_product_impl_2 |
294 | { |
295 | }; |
296 | |
297 | template<template<class...> class F, class P> struct mp_product_impl_2<F, P> |
298 | { |
299 | using type = mp_list<mp_rename<P, F>>; |
300 | }; |
301 | |
302 | 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...> |
303 | { |
304 | using type = mp_append<typename mp_product_impl_2<F, mp_push_back<P, T1>, L...>::type...>; |
305 | }; |
306 | |
307 | template<template<class...> class F, class... L> struct mp_product_impl |
308 | { |
309 | }; |
310 | |
311 | template<template<class...> class F> struct mp_product_impl<F> |
312 | { |
313 | using type = mp_list< F<> >; |
314 | }; |
315 | |
316 | template<template<class...> class F, class L1, class... L> struct mp_product_impl<F, L1, L...> |
317 | { |
318 | using type = mp_assign<L1, typename mp_product_impl_2<F, mp_list<>, L1, L...>::type>; |
319 | }; |
320 | |
321 | } // namespace detail |
322 | |
323 | template<template<class...> class F, class... L> using mp_product = typename detail::mp_product_impl<F, L...>::type; |
324 | template<class Q, class... L> using mp_product_q = typename detail::mp_product_impl<Q::template fn, L...>::type; |
325 | |
326 | // mp_drop(_c)<L, N> |
327 | namespace detail |
328 | { |
329 | |
330 | template<class L, class L2, class En> struct mp_drop_impl; |
331 | |
332 | template<template<class...> class L, class... T, template<class...> class L2, class... U> struct mp_drop_impl<L<T...>, L2<U...>, mp_true> |
333 | { |
334 | template<class... W> static mp_identity<L<W...>> f( U*..., mp_identity<W>*... ); |
335 | |
336 | using R = decltype( f( static_cast<mp_identity<T>*>(0) ... ) ); |
337 | |
338 | using type = typename R::type; |
339 | }; |
340 | |
341 | } // namespace detail |
342 | |
343 | template<class L, std::size_t N> using mp_drop_c = mp_assign<L, typename detail::mp_drop_impl<mp_rename<L, mp_list>, mp_repeat_c<mp_list<void>, N>, mp_bool<N <= mp_size<L>::value>>::type>; |
344 | |
345 | template<class L, class N> using mp_drop = mp_drop_c<L, std::size_t{ N::value }>; |
346 | |
347 | // mp_from_sequence<S, F> |
348 | namespace detail |
349 | { |
350 | |
351 | template<class S, class F> struct mp_from_sequence_impl; |
352 | |
353 | template<template<class T, T... I> class S, class U, U... J, class F> struct mp_from_sequence_impl<S<U, J...>, F> |
354 | { |
355 | using type = mp_list_c<U, (F::value + J)...>; |
356 | }; |
357 | |
358 | } // namespace detail |
359 | |
360 | template<class S, class F = mp_int<0>> using mp_from_sequence = typename detail::mp_from_sequence_impl<S, F>::type; |
361 | |
362 | // mp_iota(_c)<N, F> |
363 | template<std::size_t N, std::size_t F = 0> using mp_iota_c = mp_from_sequence<make_index_sequence<N>, mp_size_t<F>>; |
364 | template<class N, class F = mp_int<0>> using mp_iota = mp_from_sequence<make_integer_sequence<typename std::remove_const<decltype(N::value)>::type, N::value>, F>; |
365 | |
366 | // mp_at(_c)<L, I> |
367 | namespace detail |
368 | { |
369 | |
370 | template<class L, std::size_t I> struct mp_at_c_impl; |
371 | |
372 | #if defined(BOOST_MP11_HAS_TYPE_PACK_ELEMENT) |
373 | |
374 | template<template<class...> class L, class... T, std::size_t I> struct mp_at_c_impl<L<T...>, I> |
375 | { |
376 | using type = __type_pack_element<I, T...>; |
377 | }; |
378 | |
379 | #if defined(BOOST_MP11_HAS_TEMPLATE_AUTO) |
380 | |
381 | template<template<auto...> class L, auto... A, std::size_t I> struct mp_at_c_impl<L<A...>, I> |
382 | { |
383 | using type = __type_pack_element<I, mp_value<A>...>; |
384 | }; |
385 | |
386 | #endif |
387 | |
388 | #else |
389 | |
390 | template<class L, std::size_t I> struct mp_at_c_impl |
391 | { |
392 | using _map = mp_transform<mp_list, mp_iota<mp_size<L> >, mp_rename<L, mp_list>>; |
393 | using type = mp_second<mp_map_find<_map, mp_size_t<I> > >; |
394 | }; |
395 | |
396 | #endif |
397 | |
398 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) |
399 | |
400 | template<class L, std::size_t I> struct mp_at_c_cuda_workaround |
401 | { |
402 | using type = mp_if_c<(I < mp_size<L>::value), detail::mp_at_c_impl<L, I>, void>; |
403 | }; |
404 | |
405 | #endif |
406 | |
407 | } // namespace detail |
408 | |
409 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) |
410 | |
411 | template<class L, std::size_t I> using mp_at_c = typename detail::mp_at_c_cuda_workaround< L, I >::type::type; |
412 | |
413 | #else |
414 | |
415 | template<class L, std::size_t I> using mp_at_c = typename mp_if_c<(I < mp_size<L>::value), detail::mp_at_c_impl<L, I>, void>::type; |
416 | |
417 | #endif |
418 | |
419 | template<class L, class I> using mp_at = mp_at_c<L, std::size_t{ I::value }>; |
420 | |
421 | // mp_take(_c)<L, N> |
422 | namespace detail |
423 | { |
424 | |
425 | template<std::size_t N, class L, class E = void> struct mp_take_c_impl |
426 | { |
427 | }; |
428 | |
429 | template<template<class...> class L, class... T> |
430 | struct mp_take_c_impl<0, L<T...>> |
431 | { |
432 | using type = L<>; |
433 | }; |
434 | |
435 | template<template<class...> class L, class T1, class... T> |
436 | struct mp_take_c_impl<1, L<T1, T...>> |
437 | { |
438 | using type = L<T1>; |
439 | }; |
440 | |
441 | template<template<class...> class L, class T1, class T2, class... T> |
442 | struct mp_take_c_impl<2, L<T1, T2, T...>> |
443 | { |
444 | using type = L<T1, T2>; |
445 | }; |
446 | |
447 | template<template<class...> class L, class T1, class T2, class T3, class... T> |
448 | struct mp_take_c_impl<3, L<T1, T2, T3, T...>> |
449 | { |
450 | using type = L<T1, T2, T3>; |
451 | }; |
452 | |
453 | template<template<class...> class L, class T1, class T2, class T3, class T4, class... T> |
454 | struct mp_take_c_impl<4, L<T1, T2, T3, T4, T...>> |
455 | { |
456 | using type = L<T1, T2, T3, T4>; |
457 | }; |
458 | |
459 | template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class... T> |
460 | struct mp_take_c_impl<5, L<T1, T2, T3, T4, T5, T...>> |
461 | { |
462 | using type = L<T1, T2, T3, T4, T5>; |
463 | }; |
464 | |
465 | template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class... T> |
466 | struct mp_take_c_impl<6, L<T1, T2, T3, T4, T5, T6, T...>> |
467 | { |
468 | using type = L<T1, T2, T3, T4, T5, T6>; |
469 | }; |
470 | |
471 | template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class... T> |
472 | struct mp_take_c_impl<7, L<T1, T2, T3, T4, T5, T6, T7, T...>> |
473 | { |
474 | using type = L<T1, T2, T3, T4, T5, T6, T7>; |
475 | }; |
476 | |
477 | template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class... T> |
478 | struct mp_take_c_impl<8, L<T1, T2, T3, T4, T5, T6, T7, T8, T...>> |
479 | { |
480 | using type = L<T1, T2, T3, T4, T5, T6, T7, T8>; |
481 | }; |
482 | |
483 | template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class... T> |
484 | struct mp_take_c_impl<9, L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>> |
485 | { |
486 | using type = L<T1, T2, T3, T4, T5, T6, T7, T8, T9>; |
487 | }; |
488 | |
489 | template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class... T, std::size_t N> |
490 | struct mp_take_c_impl<N, L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T...>, typename std::enable_if<N >= 10>::type> |
491 | { |
492 | using type = mp_append<L<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>, typename mp_take_c_impl<N-10, L<T...>>::type>; |
493 | }; |
494 | |
495 | } // namespace detail |
496 | |
497 | template<class L, std::size_t N> using mp_take_c = mp_assign<L, typename detail::mp_take_c_impl<N, mp_rename<L, mp_list>>::type>; |
498 | template<class L, class N> using mp_take = mp_take_c<L, std::size_t{ N::value }>; |
499 | |
500 | // mp_slice(_c)<L, I, J> |
501 | template<class L, std::size_t I, std::size_t J> using mp_slice_c = mp_drop_c< mp_take_c<L, J>, I >; |
502 | template<class L, class I, class J> using mp_slice = mp_drop< mp_take<L, J>, I >; |
503 | |
504 | // mp_back<L> |
505 | template<class L> using mp_back = mp_at_c<L, mp_size<L>::value - 1>; |
506 | |
507 | // mp_pop_back<L> |
508 | template<class L> using mp_pop_back = mp_take_c<L, mp_size<L>::value - 1>; |
509 | |
510 | // mp_replace<L, V, W> |
511 | namespace detail |
512 | { |
513 | |
514 | template<class L, class V, class W> struct mp_replace_impl; |
515 | |
516 | template<template<class...> class L, class... T, class V, class W> struct mp_replace_impl<L<T...>, V, W> |
517 | { |
518 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) |
519 | template<class A> struct _f { using type = mp_if<std::is_same<A, V>, W, A>; }; |
520 | using type = L<typename _f<T>::type...>; |
521 | #else |
522 | template<class A> using _f = mp_if<std::is_same<A, V>, W, A>; |
523 | using type = L<_f<T>...>; |
524 | #endif |
525 | }; |
526 | |
527 | } // namespace detail |
528 | |
529 | template<class L, class V, class W> using mp_replace = typename detail::mp_replace_impl<L, V, W>::type; |
530 | |
531 | // mp_replace_if<L, P, W> |
532 | namespace detail |
533 | { |
534 | |
535 | template<class L, template<class...> class P, class W> struct mp_replace_if_impl; |
536 | |
537 | template<template<class...> class L, class... T, template<class...> class P, class W> struct mp_replace_if_impl<L<T...>, P, W> |
538 | { |
539 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) |
540 | template<class U> struct _f { using type = mp_if<P<U>, W, U>; }; |
541 | using type = L<typename _f<T>::type...>; |
542 | #else |
543 | template<class U> using _f = mp_if<P<U>, W, U>; |
544 | using type = L<_f<T>...>; |
545 | #endif |
546 | }; |
547 | |
548 | } // namespace detail |
549 | |
550 | template<class L, template<class...> class P, class W> using mp_replace_if = typename detail::mp_replace_if_impl<L, P, W>::type; |
551 | template<class L, class Q, class W> using mp_replace_if_q = mp_replace_if<L, Q::template fn, W>; |
552 | |
553 | // mp_copy_if<L, P> |
554 | // in detail/mp_copy_if.hpp |
555 | |
556 | // mp_remove<L, V> |
557 | namespace detail |
558 | { |
559 | |
560 | template<class L, class V> struct mp_remove_impl; |
561 | |
562 | template<template<class...> class L, class... T, class V> struct mp_remove_impl<L<T...>, V> |
563 | { |
564 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, < 1920 ) |
565 | template<class U> struct _f { using type = mp_if<std::is_same<U, V>, mp_list<>, mp_list<U>>; }; |
566 | using type = mp_append<L<>, typename _f<T>::type...>; |
567 | #else |
568 | template<class U> using _f = mp_if<std::is_same<U, V>, mp_list<>, mp_list<U>>; |
569 | using type = mp_append<L<>, _f<T>...>; |
570 | #endif |
571 | }; |
572 | |
573 | } // namespace detail |
574 | |
575 | template<class L, class V> using mp_remove = typename detail::mp_remove_impl<L, V>::type; |
576 | |
577 | // mp_remove_if<L, P> |
578 | // in detail/mp_remove_if.hpp |
579 | |
580 | // mp_flatten<L, L2 = mp_clear<L>> |
581 | namespace detail |
582 | { |
583 | |
584 | template<class L2> struct mp_flatten_impl |
585 | { |
586 | template<class T> using fn = mp_if<mp_similar<L2, T>, T, mp_list<T>>; |
587 | }; |
588 | |
589 | } // namespace detail |
590 | |
591 | template<class L, class L2 = mp_clear<L>> using mp_flatten = mp_apply<mp_append, mp_push_front<mp_transform_q<detail::mp_flatten_impl<L2>, L>, mp_clear<L>>>; |
592 | |
593 | // mp_partition<L, P> |
594 | namespace detail |
595 | { |
596 | |
597 | template<class L, template<class...> class P> struct mp_partition_impl; |
598 | |
599 | template<template<class...> class L, class... T, template<class...> class P> struct mp_partition_impl<L<T...>, P> |
600 | { |
601 | using type = L<mp_copy_if<L<T...>, P>, mp_remove_if<L<T...>, P>>; |
602 | }; |
603 | |
604 | } // namespace detail |
605 | |
606 | template<class L, template<class...> class P> using mp_partition = typename detail::mp_partition_impl<L, P>::type; |
607 | template<class L, class Q> using mp_partition_q = mp_partition<L, Q::template fn>; |
608 | |
609 | // mp_sort<L, P> |
610 | namespace detail |
611 | { |
612 | |
613 | template<class L, template<class...> class P> struct mp_sort_impl; |
614 | |
615 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) |
616 | |
617 | template<template<class...> class L, class... T, template<class...> class P> struct mp_sort_impl<L<T...>, P> |
618 | { |
619 | static_assert( sizeof...(T) == 0, "T... must be empty" ); |
620 | using type = L<>; |
621 | }; |
622 | |
623 | #else |
624 | |
625 | template<template<class...> class L, template<class...> class P> struct mp_sort_impl<L<>, P> |
626 | { |
627 | using type = L<>; |
628 | }; |
629 | |
630 | #endif |
631 | |
632 | template<template<class...> class L, class T1, template<class...> class P> struct mp_sort_impl<L<T1>, P> |
633 | { |
634 | using type = L<T1>; |
635 | }; |
636 | |
637 | template<template<class...> class L, class T1, class... T, template<class...> class P> struct mp_sort_impl<L<T1, T...>, P> |
638 | { |
639 | template<class U> using F = P<U, T1>; |
640 | |
641 | using part = mp_partition<L<T...>, F>; |
642 | |
643 | using S1 = typename mp_sort_impl<mp_first<part>, P>::type; |
644 | using S2 = typename mp_sort_impl<mp_second<part>, P>::type; |
645 | |
646 | using type = mp_append<mp_push_back<S1, T1>, S2>; |
647 | }; |
648 | |
649 | } // namespace detail |
650 | |
651 | template<class L, template<class...> class P> using mp_sort = typename detail::mp_sort_impl<L, P>::type; |
652 | template<class L, class Q> using mp_sort_q = mp_sort<L, Q::template fn>; |
653 | |
654 | // mp_nth_element(_c)<L, I, P> |
655 | namespace detail |
656 | { |
657 | |
658 | template<class L, std::size_t I, template<class...> class P> struct mp_nth_element_impl; |
659 | |
660 | template<template<class...> class L, class T1, std::size_t I, template<class...> class P> struct mp_nth_element_impl<L<T1>, I, P> |
661 | { |
662 | static_assert( I == 0, "mp_nth_element index out of range" ); |
663 | using type = T1; |
664 | }; |
665 | |
666 | template<template<class...> class L, class T1, class... T, std::size_t I, template<class...> class P> struct mp_nth_element_impl<L<T1, T...>, I, P> |
667 | { |
668 | static_assert( I < 1 + sizeof...(T), "mp_nth_element index out of range" ); |
669 | |
670 | template<class U> using F = P<U, T1>; |
671 | |
672 | using part = mp_partition<L<T...>, F>; |
673 | |
674 | using L1 = mp_first<part>; |
675 | static std::size_t const N1 = mp_size<L1>::value; |
676 | |
677 | using L2 = mp_second<part>; |
678 | |
679 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_CUDA, >= 9000000 && BOOST_MP11_CUDA < 10000000 ) |
680 | |
681 | struct detail |
682 | { |
683 | struct mp_nth_element_impl_cuda_workaround |
684 | { |
685 | using type = mp_cond< |
686 | |
687 | mp_bool<(I < N1)>, mp_nth_element_impl<L1, I, P>, |
688 | mp_bool<(I == N1)>, mp_identity<T1>, |
689 | mp_true, mp_nth_element_impl<L2, I - N1 - 1, P> |
690 | |
691 | >; |
692 | }; |
693 | }; |
694 | |
695 | using type = typename detail::mp_nth_element_impl_cuda_workaround::type::type; |
696 | |
697 | #else |
698 | |
699 | using type = typename mp_cond< |
700 | |
701 | mp_bool<(I < N1)>, mp_nth_element_impl<L1, I, P>, |
702 | mp_bool<(I == N1)>, mp_identity<T1>, |
703 | mp_true, mp_nth_element_impl<L2, I - N1 - 1, P> |
704 | |
705 | >::type; |
706 | |
707 | #endif |
708 | }; |
709 | |
710 | } // namespace detail |
711 | |
712 | template<class L, std::size_t I, template<class...> class P> using mp_nth_element_c = typename detail::mp_nth_element_impl<L, I, P>::type; |
713 | template<class L, class I, template<class...> class P> using mp_nth_element = typename detail::mp_nth_element_impl<L, std::size_t{ I::value }, P>::type; |
714 | template<class L, class I, class Q> using mp_nth_element_q = mp_nth_element<L, I, Q::template fn>; |
715 | |
716 | // mp_find<L, V> |
717 | namespace detail |
718 | { |
719 | |
720 | template<class L, class V> struct mp_find_impl; |
721 | |
722 | #if BOOST_MP11_CLANG && defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) |
723 | |
724 | struct mp_index_holder |
725 | { |
726 | std::size_t i_; |
727 | bool f_; |
728 | }; |
729 | |
730 | constexpr inline mp_index_holder operator+( mp_index_holder const & v, bool f ) |
731 | { |
732 | if( v.f_ ) |
733 | { |
734 | return v; |
735 | } |
736 | else if( f ) |
737 | { |
738 | return { .i_: v.i_, .f_: true }; |
739 | } |
740 | else |
741 | { |
742 | return { .i_: v.i_ + 1, .f_: false }; |
743 | } |
744 | } |
745 | |
746 | template<template<class...> class L, class... T, class V> struct mp_find_impl<L<T...>, V> |
747 | { |
748 | static constexpr mp_index_holder _v{ .i_: 0, .f_: false }; |
749 | using type = mp_size_t< (_v + ... + std::is_same<T, V>::value).i_ >; |
750 | }; |
751 | |
752 | #elif !defined( BOOST_MP11_NO_CONSTEXPR ) |
753 | |
754 | template<template<class...> class L, class V> struct mp_find_impl<L<>, V> |
755 | { |
756 | using type = mp_size_t<0>; |
757 | }; |
758 | |
759 | #if defined( BOOST_MP11_HAS_CXX14_CONSTEXPR ) |
760 | |
761 | constexpr std::size_t cx_find_index( bool const * first, bool const * last ) |
762 | { |
763 | std::size_t m = 0; |
764 | |
765 | while( first != last && !*first ) |
766 | { |
767 | ++m; |
768 | ++first; |
769 | } |
770 | |
771 | return m; |
772 | } |
773 | |
774 | #else |
775 | |
776 | constexpr std::size_t cx_find_index( bool const * first, bool const * last ) |
777 | { |
778 | return first == last || *first? 0: 1 + cx_find_index( first + 1, last ); |
779 | } |
780 | |
781 | #endif |
782 | |
783 | template<template<class...> class L, class... T, class V> struct mp_find_impl<L<T...>, V> |
784 | { |
785 | static constexpr bool _v[] = { std::is_same<T, V>::value... }; |
786 | using type = mp_size_t< cx_find_index( _v, _v + sizeof...(T) ) >; |
787 | }; |
788 | |
789 | #else |
790 | |
791 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) |
792 | |
793 | template<template<class...> class L, class... T, class V> struct mp_find_impl<L<T...>, V> |
794 | { |
795 | static_assert( sizeof...(T) == 0, "T... must be empty" ); |
796 | using type = mp_size_t<0>; |
797 | }; |
798 | |
799 | #else |
800 | |
801 | template<template<class...> class L, class V> struct mp_find_impl<L<>, V> |
802 | { |
803 | using type = mp_size_t<0>; |
804 | }; |
805 | |
806 | #endif |
807 | |
808 | template<template<class...> class L, class... T, class V> struct mp_find_impl<L<V, T...>, V> |
809 | { |
810 | using type = mp_size_t<0>; |
811 | }; |
812 | |
813 | template<template<class...> class L, class T1, class... T, class V> struct mp_find_impl<L<T1, T...>, V> |
814 | { |
815 | using _r = typename mp_find_impl<mp_list<T...>, V>::type; |
816 | using type = mp_size_t<1 + _r::value>; |
817 | }; |
818 | |
819 | #endif |
820 | |
821 | } // namespace detail |
822 | |
823 | template<class L, class V> using mp_find = typename detail::mp_find_impl<L, V>::type; |
824 | |
825 | // mp_find_if<L, P> |
826 | namespace detail |
827 | { |
828 | |
829 | template<class L, template<class...> class P> struct mp_find_if_impl; |
830 | |
831 | #if BOOST_MP11_CLANG && defined( BOOST_MP11_HAS_FOLD_EXPRESSIONS ) |
832 | |
833 | template<template<class...> class L, class... T, template<class...> class P> struct mp_find_if_impl<L<T...>, P> |
834 | { |
835 | static constexpr mp_index_holder _v{ .i_: 0, .f_: false }; |
836 | using type = mp_size_t< (_v + ... + P<T>::value).i_ >; |
837 | }; |
838 | |
839 | #elif !defined( BOOST_MP11_NO_CONSTEXPR ) |
840 | |
841 | template<template<class...> class L, template<class...> class P> struct mp_find_if_impl<L<>, P> |
842 | { |
843 | using type = mp_size_t<0>; |
844 | }; |
845 | |
846 | template<template<class...> class L, class... T, template<class...> class P> struct mp_find_if_impl<L<T...>, P> |
847 | { |
848 | static constexpr bool _v[] = { P<T>::value... }; |
849 | using type = mp_size_t< cx_find_index( _v, _v + sizeof...(T) ) >; |
850 | }; |
851 | |
852 | #else |
853 | |
854 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) |
855 | |
856 | template<template<class...> class L, class... T, template<class...> class P> struct mp_find_if_impl<L<T...>, P> |
857 | { |
858 | static_assert( sizeof...(T) == 0, "T... must be empty" ); |
859 | using type = mp_size_t<0>; |
860 | }; |
861 | |
862 | #else |
863 | |
864 | template<template<class...> class L, template<class...> class P> struct mp_find_if_impl<L<>, P> |
865 | { |
866 | using type = mp_size_t<0>; |
867 | }; |
868 | |
869 | #endif |
870 | |
871 | template<class L, template<class...> class P> struct mp_find_if_impl_2 |
872 | { |
873 | using _r = typename mp_find_if_impl<L, P>::type; |
874 | using type = mp_size_t<1 + _r::value>; |
875 | }; |
876 | |
877 | template<template<class...> class L, class T1, class... T, template<class...> class P> struct mp_find_if_impl<L<T1, T...>, P> |
878 | { |
879 | using type = typename mp_if<P<T1>, mp_identity<mp_size_t<0>>, mp_find_if_impl_2<mp_list<T...>, P>>::type; |
880 | }; |
881 | |
882 | #endif |
883 | |
884 | } // namespace detail |
885 | |
886 | template<class L, template<class...> class P> using mp_find_if = typename detail::mp_find_if_impl<L, P>::type; |
887 | template<class L, class Q> using mp_find_if_q = mp_find_if<L, Q::template fn>; |
888 | |
889 | // mp_reverse<L> |
890 | namespace detail |
891 | { |
892 | |
893 | template<class L> struct mp_reverse_impl; |
894 | |
895 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) |
896 | |
897 | template<template<class...> class L, class... T> struct mp_reverse_impl<L<T...>> |
898 | { |
899 | static_assert( sizeof...(T) == 0, "T... must be empty" ); |
900 | using type = L<>; |
901 | }; |
902 | |
903 | #else |
904 | |
905 | template<template<class...> class L> struct mp_reverse_impl<L<>> |
906 | { |
907 | using type = L<>; |
908 | }; |
909 | |
910 | #endif |
911 | |
912 | template<template<class...> class L, class T1> struct mp_reverse_impl<L<T1>> |
913 | { |
914 | using type = L<T1>; |
915 | }; |
916 | |
917 | template<template<class...> class L, class T1, class T2> struct mp_reverse_impl<L<T1, T2>> |
918 | { |
919 | using type = L<T2, T1>; |
920 | }; |
921 | |
922 | template<template<class...> class L, class T1, class T2, class T3> struct mp_reverse_impl<L<T1, T2, T3>> |
923 | { |
924 | using type = L<T3, T2, T1>; |
925 | }; |
926 | |
927 | template<template<class...> class L, class T1, class T2, class T3, class T4> struct mp_reverse_impl<L<T1, T2, T3, T4>> |
928 | { |
929 | using type = L<T4, T3, T2, T1>; |
930 | }; |
931 | |
932 | 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>> |
933 | { |
934 | using type = L<T5, T4, T3, T2, T1>; |
935 | }; |
936 | |
937 | 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>> |
938 | { |
939 | using type = L<T6, T5, T4, T3, T2, T1>; |
940 | }; |
941 | |
942 | 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>> |
943 | { |
944 | using type = L<T7, T6, T5, T4, T3, T2, T1>; |
945 | }; |
946 | |
947 | 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>> |
948 | { |
949 | using type = L<T8, T7, T6, T5, T4, T3, T2, T1>; |
950 | }; |
951 | |
952 | 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>> |
953 | { |
954 | using type = L<T9, T8, T7, T6, T5, T4, T3, T2, T1>; |
955 | }; |
956 | |
957 | 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...>> |
958 | { |
959 | using type = mp_push_back<typename mp_reverse_impl<L<T...>>::type, T10, T9, T8, T7, T6, T5, T4, T3, T2, T1>; |
960 | }; |
961 | |
962 | } // namespace detail |
963 | |
964 | template<class L> using mp_reverse = typename detail::mp_reverse_impl<L>::type; |
965 | |
966 | // mp_fold<L, V, F> |
967 | // in detail/mp_fold.hpp |
968 | |
969 | // mp_reverse_fold<L, V, F> |
970 | namespace detail |
971 | { |
972 | |
973 | template<class L, class V, template<class...> class F> struct mp_reverse_fold_impl; |
974 | |
975 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) |
976 | |
977 | template<template<class...> class L, class... T, class V, template<class...> class F> struct mp_reverse_fold_impl<L<T...>, V, F> |
978 | { |
979 | static_assert( sizeof...(T) == 0, "T... must be empty" ); |
980 | using type = V; |
981 | }; |
982 | |
983 | #else |
984 | |
985 | template<template<class...> class L, class V, template<class...> class F> struct mp_reverse_fold_impl<L<>, V, F> |
986 | { |
987 | using type = V; |
988 | }; |
989 | |
990 | #endif |
991 | |
992 | 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> |
993 | { |
994 | using rest = typename mp_reverse_fold_impl<L<T...>, V, F>::type; |
995 | using type = F<T1, rest>; |
996 | }; |
997 | |
998 | 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> |
999 | { |
1000 | using rest = typename mp_reverse_fold_impl<L<T...>, V, F>::type; |
1001 | using type = F<T1, F<T2, F<T3, F<T4, F<T5, F<T6, F<T7, F<T8, F<T9, F<T10, rest> > > > > > > > > >; |
1002 | }; |
1003 | |
1004 | } // namespace detail |
1005 | |
1006 | template<class L, class V, template<class...> class F> using mp_reverse_fold = typename detail::mp_reverse_fold_impl<L, V, F>::type; |
1007 | template<class L, class V, class Q> using mp_reverse_fold_q = mp_reverse_fold<L, V, Q::template fn>; |
1008 | |
1009 | // mp_unique<L> |
1010 | namespace detail |
1011 | { |
1012 | |
1013 | template<class L> struct mp_unique_impl; |
1014 | |
1015 | template<template<class...> class L, class... T> struct mp_unique_impl<L<T...>> |
1016 | { |
1017 | using type = mp_set_push_back<L<>, T...>; |
1018 | }; |
1019 | |
1020 | } // namespace detail |
1021 | |
1022 | template<class L> using mp_unique = typename detail::mp_unique_impl<L>::type; |
1023 | |
1024 | // mp_unique_if<L, P> |
1025 | namespace detail |
1026 | { |
1027 | |
1028 | template<template<class...> class P> struct mp_unique_if_push_back |
1029 | { |
1030 | template<class...> struct impl |
1031 | { |
1032 | }; |
1033 | |
1034 | template<template<class...> class L, class... Ts, class T> |
1035 | struct impl<L<Ts...>, T> |
1036 | { |
1037 | using type = mp_if<mp_any<P<Ts, T>...>, L<Ts...>, L<Ts..., T>>; |
1038 | }; |
1039 | |
1040 | template<class... T> using fn = typename impl<T...>::type; |
1041 | }; |
1042 | |
1043 | } // namespace detail |
1044 | |
1045 | template<class L, template<class...> class P> |
1046 | using mp_unique_if = mp_fold_q<L, mp_clear<L>, detail::mp_unique_if_push_back<P>>; |
1047 | |
1048 | template<class L, class Q> using mp_unique_if_q = mp_unique_if<L, Q::template fn>; |
1049 | |
1050 | // mp_all_of<L, P> |
1051 | template<class L, template<class...> class P> using mp_all_of = mp_bool< mp_count_if<L, P>::value == mp_size<L>::value >; |
1052 | template<class L, class Q> using mp_all_of_q = mp_all_of<L, Q::template fn>; |
1053 | |
1054 | // mp_none_of<L, P> |
1055 | template<class L, template<class...> class P> using mp_none_of = mp_bool< mp_count_if<L, P>::value == 0 >; |
1056 | template<class L, class Q> using mp_none_of_q = mp_none_of<L, Q::template fn>; |
1057 | |
1058 | // mp_any_of<L, P> |
1059 | template<class L, template<class...> class P> using mp_any_of = mp_bool< mp_count_if<L, P>::value != 0 >; |
1060 | template<class L, class Q> using mp_any_of_q = mp_any_of<L, Q::template fn>; |
1061 | |
1062 | // mp_replace_at_c<L, I, W> |
1063 | namespace detail |
1064 | { |
1065 | |
1066 | template<class L, class I, class W> struct mp_replace_at_impl |
1067 | { |
1068 | static_assert( I::value >= 0, "mp_replace_at<L, I, W>: I must not be negative" ); |
1069 | |
1070 | template<class T1, class T2> using _p = std::is_same<T2, mp_size_t<I::value>>; |
1071 | template<class T1, class T2> using _f = W; |
1072 | |
1073 | using type = mp_transform_if<_p, _f, L, mp_iota<mp_size<L> > >; |
1074 | }; |
1075 | |
1076 | } // namespace detail |
1077 | |
1078 | template<class L, class I, class W> using mp_replace_at = typename detail::mp_replace_at_impl<L, I, W>::type; |
1079 | 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; |
1080 | |
1081 | //mp_for_each<L>(f) |
1082 | namespace detail |
1083 | { |
1084 | |
1085 | template<class... T, class F> BOOST_MP11_CONSTEXPR F mp_for_each_impl( mp_list<T...>, F && f ) |
1086 | { |
1087 | using A = int[sizeof...(T)]; |
1088 | return (void)A{ ((void)f(T()), 0)... }, std::forward<F>(f); |
1089 | } |
1090 | |
1091 | template<class F> BOOST_MP11_CONSTEXPR F mp_for_each_impl( mp_list<>, F && f ) |
1092 | { |
1093 | return std::forward<F>(f); |
1094 | } |
1095 | |
1096 | } // namespace detail |
1097 | |
1098 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, >= 1900 ) |
1099 | |
1100 | // msvc has a limit of 1024 |
1101 | |
1102 | template<class L, class F> BOOST_MP11_CONSTEXPR mp_if_c<mp_size<L>::value <= 1024, F> mp_for_each( F && f ) |
1103 | { |
1104 | return detail::mp_for_each_impl( mp_rename<L, mp_list>(), std::forward<F>(f) ); |
1105 | } |
1106 | |
1107 | template<class L, class F> BOOST_MP11_CONSTEXPR mp_if_c<mp_size<L>::value >= 1025, F> mp_for_each( F && f ) |
1108 | { |
1109 | using L2 = mp_rename<L, mp_list>; |
1110 | |
1111 | using L3 = mp_take_c<L2, 1024>; |
1112 | using L4 = mp_drop_c<L2, 1024>; |
1113 | |
1114 | return mp_for_each<L4>( mp_for_each<L3>( std::forward<F>(f) ) ); |
1115 | } |
1116 | |
1117 | #else |
1118 | |
1119 | template<class L, class F> BOOST_MP11_CONSTEXPR F mp_for_each( F && f ) |
1120 | { |
1121 | return detail::mp_for_each_impl( mp_rename<L, mp_list>(), std::forward<F>(f) ); |
1122 | } |
1123 | |
1124 | #endif |
1125 | |
1126 | // mp_insert<L, I, T...> |
1127 | template<class L, class I, class... T> using mp_insert = mp_append<mp_take<L, I>, mp_push_front<mp_drop<L, I>, T...>>; |
1128 | |
1129 | // mp_insert_c<L, I, T...> |
1130 | 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...>>; |
1131 | |
1132 | // mp_erase<L, I, J> |
1133 | template<class L, class I, class J> using mp_erase = mp_append<mp_take<L, I>, mp_drop<L, J>>; |
1134 | |
1135 | // mp_erase_c<L, I, J> |
1136 | 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>>; |
1137 | |
1138 | // mp_starts_with<L1, L2> |
1139 | // contributed by Glen Joseph Fernandes (glenjofe@gmail.com) |
1140 | namespace detail { |
1141 | |
1142 | template<class L1, class L2> |
1143 | struct mp_starts_with_impl { }; |
1144 | |
1145 | template<template<class...> class L1, class... T1, template<class...> class L2, |
1146 | class... T2> |
1147 | struct mp_starts_with_impl<L1<T1...>, L2<T2...> > { |
1148 | template<class L> |
1149 | static mp_false check(L); |
1150 | |
1151 | template<class... T> |
1152 | static mp_true check(mp_list<T2..., T...>); |
1153 | |
1154 | using type = decltype(check(mp_list<T1...>())); |
1155 | }; |
1156 | |
1157 | } // namespace detail |
1158 | |
1159 | template<class L1, class L2> |
1160 | using mp_starts_with = typename detail::mp_starts_with_impl<L1, L2>::type; |
1161 | |
1162 | // mp_rotate_left(_c)<L, N> |
1163 | namespace detail |
1164 | { |
1165 | |
1166 | // limit divisor to 1 to avoid division by 0 and give a rotation of 0 for lists containing 0 or 1 elements |
1167 | template<std::size_t Ln, std::size_t N> using canonical_left_rotation = mp_size_t<N % (Ln == 0? 1: Ln)>; |
1168 | |
1169 | // perform right rotation as a left rotation by inverting the number of elements to rotate |
1170 | template<std::size_t Ln, std::size_t N> using canonical_right_rotation = mp_size_t<Ln - N % (Ln == 0? 1: Ln)>; |
1171 | |
1172 | // avoid errors when rotating fixed-sized lists by using mp_list for the transformation |
1173 | template<class L, class N, class L2 = mp_rename<L, mp_list>> using mp_rotate_impl = mp_assign<L, mp_append< mp_drop<L2, N>, mp_take<L2, N> >>; |
1174 | |
1175 | } // namespace detail |
1176 | |
1177 | template<class L, std::size_t N> using mp_rotate_left_c = detail::mp_rotate_impl<L, detail::canonical_left_rotation<mp_size<L>::value, N>>; |
1178 | template<class L, class N> using mp_rotate_left = mp_rotate_left_c<L, std::size_t{ N::value }>; |
1179 | |
1180 | // mp_rotate_right(_c)<L, N> |
1181 | template<class L, std::size_t N> using mp_rotate_right_c = mp_rotate_left<L, detail::canonical_right_rotation<mp_size<L>::value, N>>; |
1182 | template<class L, class N> using mp_rotate_right = mp_rotate_right_c<L, std::size_t{ N::value }>; |
1183 | |
1184 | // mp_min_element<L, P> |
1185 | // mp_max_element<L, P> |
1186 | // in detail/mp_min_element.hpp |
1187 | |
1188 | // mp_power_set<L> |
1189 | namespace detail |
1190 | { |
1191 | |
1192 | template<class L> struct mp_power_set_impl; |
1193 | |
1194 | } // namespace detail |
1195 | |
1196 | template<class L> using mp_power_set = typename detail::mp_power_set_impl<L>::type; |
1197 | |
1198 | namespace detail |
1199 | { |
1200 | |
1201 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) |
1202 | |
1203 | template<template<class...> class L, class... T> struct mp_power_set_impl< L<T...> > |
1204 | { |
1205 | static_assert( sizeof...(T) == 0, "T... must be empty" ); |
1206 | using type = L< L<> >; |
1207 | }; |
1208 | |
1209 | #else |
1210 | |
1211 | template<template<class...> class L> struct mp_power_set_impl< L<> > |
1212 | { |
1213 | using type = L< L<> >; |
1214 | }; |
1215 | |
1216 | #endif |
1217 | |
1218 | template<template<class...> class L, class T1, class... T> struct mp_power_set_impl< L<T1, T...> > |
1219 | { |
1220 | using S1 = mp_power_set< L<T...> >; |
1221 | |
1222 | template<class L2> using _f = mp_push_front<L2, T1>; |
1223 | |
1224 | using S2 = mp_transform<_f, S1>; |
1225 | |
1226 | using type = mp_append< S1, S2 >; |
1227 | }; |
1228 | |
1229 | } // namespace detail |
1230 | |
1231 | // mp_partial_sum<L, V, F> |
1232 | namespace detail |
1233 | { |
1234 | |
1235 | template<template<class...> class F> struct mp_partial_sum_impl_f |
1236 | { |
1237 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1900 ) |
1238 | |
1239 | template<class V, class T> using fn = mp_list<F<mp_first<V>, T>, mp_push_back<mp_second<V>, F<mp_first<V>, T>> >; |
1240 | |
1241 | #else |
1242 | |
1243 | template<class V, class T, class N = F<mp_first<V>, T>> using fn = mp_list<N, mp_push_back<mp_second<V>, N>>; |
1244 | |
1245 | #endif |
1246 | }; |
1247 | |
1248 | } // namespace detail |
1249 | |
1250 | template<class L, class V, template<class...> class F> using mp_partial_sum = mp_second<mp_fold_q<L, mp_list<V, mp_clear<L>>, detail::mp_partial_sum_impl_f<F>> >; |
1251 | template<class L, class V, class Q> using mp_partial_sum_q = mp_partial_sum<L, V, Q::template fn>; |
1252 | |
1253 | // mp_iterate<V, F, R> |
1254 | namespace detail |
1255 | { |
1256 | |
1257 | template<class V, template<class...> class F, template<class...> class R, class N> struct mp_iterate_impl; |
1258 | |
1259 | } // namespace detail |
1260 | |
1261 | template<class V, template<class...> class F, template<class...> class R> using mp_iterate = typename detail::mp_iterate_impl<V, F, R, mp_valid<R, V>>::type; |
1262 | |
1263 | namespace detail |
1264 | { |
1265 | |
1266 | template<class V, template<class...> class F, template<class...> class R> struct mp_iterate_impl<V, F, R, mp_false> |
1267 | { |
1268 | template<class X> using _f = mp_list<F<X>>; |
1269 | using type = mp_eval_or<mp_list<>, _f, V>; |
1270 | }; |
1271 | |
1272 | template<class V, template<class...> class F, template<class...> class R> struct mp_iterate_impl<V, F, R, mp_true> |
1273 | { |
1274 | using type = mp_push_front<mp_iterate<R<V>, F, R>, F<V>>; |
1275 | }; |
1276 | |
1277 | } // namespace detail |
1278 | |
1279 | template<class V, class Qf, class Qr> using mp_iterate_q = mp_iterate<V, Qf::template fn, Qr::template fn>; |
1280 | |
1281 | // mp_pairwise_fold<L, F> |
1282 | namespace detail |
1283 | { |
1284 | |
1285 | template<class L, class Q> using mp_pairwise_fold_impl = mp_transform_q<Q, mp_pop_back<L>, mp_pop_front<L>>; |
1286 | |
1287 | } // namespace detail |
1288 | |
1289 | template<class L, class Q> using mp_pairwise_fold_q = mp_eval_if<mp_empty<L>, mp_clear<L>, detail::mp_pairwise_fold_impl, L, Q>; |
1290 | template<class L, template<class...> class F> using mp_pairwise_fold = mp_pairwise_fold_q<L, mp_quote<F>>; |
1291 | |
1292 | // mp_sliding_fold<L, N, F> |
1293 | namespace detail |
1294 | { |
1295 | |
1296 | template<class C, class L, class Q, class S> struct mp_sliding_fold_impl; |
1297 | |
1298 | template<class L, class N, class Q> struct mp_sliding_fold_impl<mp_true, L, N, Q> |
1299 | { |
1300 | static const std::size_t M = mp_size<L>::value - N::value + 1; |
1301 | |
1302 | template<class I> using F = mp_slice_c<L, I::value, I::value + M>; |
1303 | |
1304 | using J = mp_transform<F, mp_iota<N>>; |
1305 | |
1306 | using type = mp_apply<mp_transform_q, mp_push_front<J, Q>>; |
1307 | }; |
1308 | |
1309 | template<class L, class N, class Q> struct mp_sliding_fold_impl<mp_false, L, N, Q> |
1310 | { |
1311 | using type = mp_clear<L>; |
1312 | }; |
1313 | |
1314 | } // namespace detail |
1315 | |
1316 | template<class L, class N, class Q> using mp_sliding_fold_q = typename detail::mp_sliding_fold_impl<mp_bool<(mp_size<L>::value >= N::value)>, L, N, Q>::type; |
1317 | template<class L, class N, template<class...> class F> using mp_sliding_fold = mp_sliding_fold_q<L, N, mp_quote<F>>; |
1318 | |
1319 | // mp_intersperse<L, S> |
1320 | namespace detail |
1321 | { |
1322 | |
1323 | template<class L, class S> struct mp_intersperse_impl |
1324 | { |
1325 | }; |
1326 | |
1327 | #if BOOST_MP11_WORKAROUND( BOOST_MP11_MSVC, <= 1800 ) |
1328 | |
1329 | template<template<class...> class L, class... T, class S> struct mp_intersperse_impl<L<T...>, S> |
1330 | { |
1331 | static_assert( sizeof...(T) == 0, "T... must be empty" ); |
1332 | using type = L<>; |
1333 | }; |
1334 | |
1335 | #else |
1336 | |
1337 | template<template<class...> class L, class S> struct mp_intersperse_impl<L<>, S> |
1338 | { |
1339 | using type = L<>; |
1340 | }; |
1341 | |
1342 | #endif |
1343 | |
1344 | template<template<class...> class L, class T1, class... T, class S> struct mp_intersperse_impl<L<T1, T...>, S> |
1345 | { |
1346 | using type = mp_append<L<T1>, L<S, T>...>; |
1347 | }; |
1348 | |
1349 | } // namespace detail |
1350 | |
1351 | template<class L, class S> using mp_intersperse = typename detail::mp_intersperse_impl<L, S>::type; |
1352 | |
1353 | // mp_split<L, S> |
1354 | namespace detail |
1355 | { |
1356 | |
1357 | template<class L, class S, class J> struct mp_split_impl; |
1358 | |
1359 | } // namespace detail |
1360 | |
1361 | template<class L, class S> using mp_split = typename detail::mp_split_impl<L, S, mp_find<L, S>>::type; |
1362 | |
1363 | namespace detail |
1364 | { |
1365 | |
1366 | template<class L, class S, class J> using mp_split_impl_ = mp_push_front<mp_split<mp_drop_c<L, J::value + 1>, S>, mp_take<L, J>>; |
1367 | |
1368 | template<class L, class S, class J> struct mp_split_impl |
1369 | { |
1370 | using type = mp_eval_if_c<mp_size<L>::value == J::value, mp_push_back<mp_clear<L>, L>, mp_split_impl_, L, S, J>; |
1371 | }; |
1372 | |
1373 | } // namespace detail |
1374 | |
1375 | // mp_join<L, S> |
1376 | |
1377 | template<class L, class S> using mp_join = mp_apply<mp_append, mp_intersperse<L, mp_list<S>>>; |
1378 | |
1379 | } // namespace mp11 |
1380 | } // namespace boost |
1381 | |
1382 | #if defined(_MSC_VER) || defined(__GNUC__) |
1383 | # pragma pop_macro( "I" ) |
1384 | #endif |
1385 | |
1386 | #endif // #ifndef BOOST_MP11_ALGORITHM_HPP_INCLUDED |
1387 | |