• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1////
2Copyright 2017-2019 Peter Dimov
3
4Distributed under the Boost Software License, Version 1.0.
5
6See accompanying file LICENSE_1_0.txt or copy at
7http://www.boost.org/LICENSE_1_0.txt
8////
9
10[#algorithm]
11# Algorithms, <boost/mp11/algorithm.hpp>
12:toc:
13:toc-title:
14:idprefix:
15
16## mp_transform<F, L...>
17
18    template<template<class...> class F, class... L> using mp_transform = /*...*/;
19
20`mp_transform<F, L1<T1...>, L2<T2...>, ..., Ln<Tn...>>` applies `F` to each successive tuple of elements and returns `L1<F<T1, T2, ..., Tn>...>`.
21
22.Using mp_transform to produce a list of pointers from a list of pointees
23```
24template<class T> using add_pointer_t =
25    typename std::add_pointer<T>::type;  // std::add_pointer_t in C++14
26
27using L1 = std::tuple<void, int, float>;
28using R1 = mp_transform<add_pointer_t, L1>; // std::tuple<void*, int*, float*>
29```
30
31.Using mp_transform to compare the contents of two lists of types
32```
33using L1 = std::tuple<void, int, float>;
34using L2 = mp_list<void, int, float>;
35
36using R1 = mp_apply<mp_all, mp_transform<std::is_same, L1, L2>>; // mp_true
37```
38
39.Using mp_transform to compare the contents of two lists of integral constants
40```
41template<class T1, class T2> using eq = mp_bool<T1::value == T2::value>;
42
43using L1 = std::tuple<mp_int<1>, mp_int<2>, mp_int<3>>;
44using L2 = mp_list<mp_size_t<1>, mp_size_t<2>, mp_size_t<3>>;
45
46using R1 = mp_apply<mp_all, mp_transform<eq, L1, L2>>; // mp_true
47```
48
49.mp_transform on one list
50[cols="<.^4m,4*^.^1m",width=85%]
51|===
52|*L1*|A~1~|A~2~|...|A~n~
535+|
54|*mp_transform<F, L1>*|F<A~1~>|F<A~2~>|...|F<A~n~>
55|===
56
57.mp_transform on two lists
58[cols="<.^4m,4*^.^1m",width=85%]
59|===
60|*L1*|A~1~|A~2~|...|A~n~
615+|
62|*L2*|B~1~|B~2~|...|B~n~
635+|
64|*mp_transform<F, L1, L2>*|F<A~1~,B~1~>|F<A~2~,B~2~>|...|F<A~n~,B~n~>
65|===
66
67## mp_transform_q<Q, L...>
68
69    template<class Q, class... L> using mp_transform_q =
70        mp_transform<Q::template fn, L...>;
71
72As `mp_transform`, but takes a quoted metafunction.
73
74.Using mp_transform_q to count the occurrences of `void` in a list
75```
76using L1 = std::tuple<void, int, float, void, int>;
77
78using R1 = mp_apply<mp_plus,
79    mp_transform_q<mp_bind_front<std::is_same, void>, L1>>; // mp_int\<2>
80```
81
82[cols="<.^4m,4*^.^1m",width=85%]
83.mp_transform_q on two lists
84|===
85|*L1*|A~1~|A~2~|...|A~n~
865+|
87|*L2*|B~1~|B~2~|...|B~n~
885+|
89|*mp_transform_q<Q, L1, L2>*|Q::fn<A~1~,B~1~>|Q::fn<A~2~,B~2~>|...|Q::fn<A~n~,B~n~>
90|===
91
92## mp_transform_if<P, F, L...>
93
94    template<template<class...> class P, template<class...> class F, class... L>
95        using mp_transform_if = /*...*/;
96
97`mp_transform_if<P, F, L1, L2, ..., Ln>` replaces the elements of the list `L1` for which `mp_to_bool<P<T1, T2, ..., Tn>>` is `mp_true` with
98`F<T1, T2, ..., Tn>`, and returns the result, where `Ti` are the corresponding elements of `Li`.
99
100.Using mp_transform_if to replace the occurrences of 'void' in a list with the corresponding elements of a second list
101```
102using L1 = std::tuple<void, int, float, void, int>;
103using L2 = std::tuple<char[1], char[2], char[3], char[4], char[5]>;
104
105template<class T1, class T2> using first_is_void = std::is_same<T1, void>;
106template<class T1, class T2> using second = T2;
107
108using R1 = mp_transform_if<first_is_void, second, L1, L2>;
109  // std::tuple<char[1], int, float, char[4], int>
110```
111
112.mp_transform_if
113[cols="<.^4m,4*^.^1m",width=85%]
114|===
115|*L1*|A~1~|A~2~|...|A~n~
1165+|
117|*L2*|B~1~|B~2~|...|B~n~
1185+|
119|*P<A~i~, B~i~>*|mp_false|mp_true|...|mp_false
1205+|
121|*mp_transform_if<P, F, L1, L2>*|A~1~|F<A~2~,B~2~>|...|A~n~
122|===
123
124## mp_transform_if_q<Qp, Qf, L...>
125
126    template<class Qp, class Qf, class... L> using mp_transform_if_q =
127        mp_transform_if<Qp::template fn, Qf::template fn, L...>;
128
129As `mp_transform_if`, but takes quoted metafunctions.
130
131.Using mp_transform_if_q to replace the occurrences of 'void' in a list with the corresponding elements of a second list
132```
133using L1 = std::tuple<void, int, float, void, int>;
134using L2 = std::tuple<char[1], char[2], char[3], char[4], char[5]>;
135
136using R1 = mp_transform_if_q<mp_bind<std::is_same, _1, void>, _2, L1, L2>;
137  // std::tuple<char[1], int, float, char[4], int>
138```
139
140.mp_transform_if_q
141[cols="<.^4m,4*^.^1m",width=85%]
142|===
143|*L1*|A~1~|A~2~|...|A~n~
1445+|
145|*L2*|B~1~|B~2~|...|B~n~
1465+|
147|*Qp::fn<A~i~, B~i~>*|mp_false|mp_true|...|mp_false
1485+|
149|*mp_transform_if_q<Qp, _2, L1, L2>*|A~1~|B~2~|...|A~n~
150|===
151
152## mp_filter<P, L...>
153
154    template<template<class...> class P, class... L> using mp_filter = /*...*/;
155
156`mp_filter<P, L1, L2, ..., Ln>` removes the elements of the list `L1` for which `mp_to_bool<P<T1, T2, ..., Tn>>`
157is `mp_false` and returns the result, where `Ti` are the corresponding elements of `Li`.
158
159See also `mp_copy_if` and `mp_remove_if`, less general variants of `mp_filter` that only take a single list.
160
161## mp_filter_q<Qp, L...>
162
163    template<class Qp, class... L> using mp_filter_q =
164        mp_filter<Qp::template fn, L...>;
165
166As `mp_filter`, but takes a quoted metafunction.
167
168.Using mp_filter_q to pick elements of a list based on a mask in another list
169```
170using L1 = std::tuple<void, int, float>;
171using L2 = mp_list<mp_true, mp_false, mp_true>;
172using R1 = mp_filter_q<_2, L1, L2>; // std::tuple<void, float>
173```
174
175## mp_fill<L, V>
176
177    template<class L, class V> using mp_fill = /*...*/;
178
179`mp_fill<L<T...>, V>` returns `L<V, V, ..., V>`, with the result having the same size as the input.
180
181.Using mp_fill with std::tuple
182```
183using L1 = std::tuple<void, int, float>;
184using R1 = mp_fill<L1, double>; // std::tuple<double, double, double>
185```
186
187.Using mp_fill with std::pair
188```
189using L1 = std::pair<int, float>;
190using R1 = mp_fill<L1, void>; // std::pair<void, void>
191```
192
193.mp_fill
194[cols="<.^4m,4*^.^1m",width=85%]
195|===
196|*L1*|A~1~|A~2~|...|A~n~
1975+|
198|*mp_fill<L1, V>*|V|V|...|V
199|===
200
201## mp_count<L, V>
202
203    template<class L, class V> using mp_count = /*...*/;
204
205`mp_count<L, V>` returns `mp_size_t<N>`, where `N` is the number of elements of `L` same as `V`.
206
207## mp_count_if<L, P>
208
209    template<class L, template<class...> class P> using mp_count_if = /*...*/;
210
211`mp_count_if<L, P>` returns `mp_size_t<N>`, where `N` is the number of elements `T` of `L` for which `mp_to_bool<P<T>>` is `mp_true`.
212
213## mp_count_if_q<L, Q>
214
215    template<class L, class Q> using mp_count_if_q = mp_count_if<L, Q::template fn>;
216
217As `mp_count_if`, but takes a quoted metafunction.
218
219## mp_contains<L, V>
220
221    template<class L, class V> using mp_contains = mp_to_bool<mp_count<L, V>>;
222
223`mp_contains<L, V>` is `mp_true` when `L` contains an element `V`, `mp_false` otherwise.
224
225## mp_starts_with<L1, L2>
226
227    template<class L1, class L2> using mp_starts_with = /*...*/;
228
229`mp_starts_with<L1, L2>` is `mp_true` when `L1` starts with `L2`, `mp_false`
230otherwise.
231
232## mp_repeat_c<L, N>
233
234    template<class L, std::size_t N> using mp_repeat_c = /*...*/;
235
236`mp_repeat_c<L, N>` returns a list of the same form as `L` that consists of `N` concatenated copies of `L`.
237
238.Using mp_repeat_c
239```
240using L1 = tuple<int>;
241using R1 = mp_repeat_c<L1, 3>; // tuple<int, int, int>
242
243using L2 = pair<int, float>;
244using R2 = mp_repeat_c<L2, 1>; // pair<int, float>
245
246using L3 = mp_list<int, float>;
247using R3 = mp_repeat_c<L3, 2>; // mp_list<int, float, int, float>
248
249using L4 = mp_list<int, float, double>;
250using R4 = mp_repeat_c<L4, 0>; // mp_list<>
251```
252
253## mp_repeat<L, N>
254
255    template<class L, class N> using mp_repeat = /*...*/;
256
257Same as `mp_repeat_c` but with a type argument `N`. The number of copies is `N::value` and must be nonnegative.
258
259## mp_product<F, L...>
260
261    template<template<class...> class F, class... L> using mp_product = /*...*/;
262
263`mp_product<F, L1<T1...>, L2<T2...>, ..., Ln<Tn...>>` evaluates `F<U1, U2, ..., Un>` for values `Ui` taken from
264the Cartesian product of the lists, as if the elements `Ui` are formed by `n` nested loops, each traversing `Li`.
265It returns a list of the form `L1<V...>` containing the results of the application of `F`. The degenerate case
266of zero lists, `mp_product<F>`, returns `mp_list<F<>>`.
267
268.mp_product on two lists
269[cols="<.^4m,4*^.^1m",width=85%]
270|===
271|*L1*|A~1~|A~2~|...|A~n~
2725+|
273|*L2*|B~1~|B~2~|...|B~m~
2745+|
275|*mp_product<F, L1, L2>*|F<A~1~,B~1~>|F<A~1~,B~2~>|...|F<A~1~,B~m~>
276||F<A~2~,B~1~>|F<A~2~,B~2~>|...|F<A~2~,B~m~>
277|
2784+|...
279||F<A~n~,B~1~>|F<A~n~,B~2~>|...|F<A~n~,B~m~>
280|===
281
282## mp_product_q<Q, L...>
283
284    template<class Q, class... L> using mp_product_q = mp_product<Q::template fn, L...>;
285
286As `mp_product`, but takes a quoted metafunction.
287
288## mp_power_set<L>
289
290    template<class L> using mp_power_set = /*...*/;
291
292`mp_power_set<L>` returns a list (of the same form as `L`) of all possible 2^n^ subsets of `L` (where `n` is the length of `L`.)
293
294`mp_power_set<L<>>` returns `L<L<>>`.
295
296`mp_power_set<L<T1>>` returns `L<L<>, L<T1>>`.
297
298`mp_power_set<L<T1, T2>>` returns `L<L<>, L<T2>, L<T1>, L<T1, T2>>`.
299
300`mp_power_set<L<T1, T...>>` returns the concatenation of `mp_power_set<L<T...>>` and that same list with `T1` prepended to each element.
301
302## mp_drop_c<L, N>
303
304    template<class L, std::size_t N> using mp_drop_c = /*...*/;
305
306`mp_drop_c<L, N>` removes the first `N` elements of `L` and returns the result.
307
308.mp_drop_c
309[cols="<.^4m,6*^.^1m",width=85%]
310|===
311|*L1*|A~1~|...|A~m~|A~m+1~|...|A~n~
3127+|
313|*mp_drop_c<L1, M>*|A~m+1~|...|A~n~ 3+|
314|===
315
316## mp_drop<L, N>
317
318    template<class L, class N> using mp_drop = /*...*/;
319
320Same as `mp_drop_c`, but with a type argument `N`. `N::value` must be a nonnegative number.
321
322## mp_from_sequence<S>
323
324    template<class S> using mp_from_sequence = /*...*/
325
326`mp_from_sequence` transforms an integer sequence produced by `make_integer_sequence` into an `mp_list`
327of the corresponding `std::integral_constant` types. Given
328
329    template<class T, T... I> struct S;
330
331`mp_from_sequence<S<T, I...>>` is an alias for `mp_list<std::integral_constant<T, I>...>`.
332
333## mp_iota_c<N>
334
335    template<std::size_t N> using mp_iota_c = /*...*/;
336
337`mp_iota_c<N>` is an alias for `mp_list<mp_size_t<0>, mp_size_t<1>, ..., mp_size_t<N-1>>`.
338
339## mp_iota<N>
340
341    template<class N> using mp_iota = /*...*/;
342
343Same as `mp_iota_c`, but with a type argument `N`. `N::value` must be a nonnegative number. Returns
344`mp_list<std::integral_constant<T, 0>, std::integral_constant<T, 1>, ..., std::integral_constant<T, N::value-1>>`
345where `T` is the type of `N::value`.
346
347.mp_iota
348[cols="<.^4m,4*^.^1m",width=85%]
349|===
350|*mp_iota<mp_int<4>>*|mp_int<0>|mp_int<1>|mp_int<2>|mp_int<3>
351|===
352
353## mp_at_c<L, I>
354
355    template<class L, std::size_t I> using mp_at_c = /*...*/;
356
357`mp_at_c<L, I>` returns the `I`-th element of `L`, zero-based.
358
359## mp_at<L, I>
360
361    template<class L, class I> using mp_at = /*...*/;
362
363Same as `mp_at_c`, but with a type argument `I`. `I::value` must be a nonnegative number.
364
365## mp_take_c<L, N>
366
367    template<class L, std::size_t N> using mp_take_c = /*...*/;
368
369`mp_take_c<L, N>` returns a list of the same form as `L` containing the first `N` elements of `L`.
370
371.mp_take_c
372[cols="<.^4m,6*^.^1m",width=85%]
373|===
374|*L1*|A~1~|...|A~m~|A~m+1~|...|A~n~
3757+|
376|*mp_take_c<L1, M>*|A~1~|...|A~m~ 3+|
377|===
378
379## mp_take<L, N>
380
381    template<class L, class N> using mp_take = /*...*/;
382
383Same as `mp_take_c`, but with a type argument `N`. `N::value` must be a nonnegative number.
384
385## mp_back<L>
386
387    template<class L> using mp_back = mp_at_c<L, mp_size<L>::value - 1>;
388
389`mp_back<L>` returns the last element of the list `L`.
390
391## mp_pop_back<L>
392
393    template<class L> using mp_pop_back = mp_take_c<L, mp_size<L>::value - 1>;
394
395`mp_pop_back<L>` removes the last element of the list `L` and returns the result.
396
397## mp_insert_c<L, I, T...>
398
399    template<class L, std::size_t I, class... T> using mp_insert_c =
400        mp_append<mp_take_c<L, I>, mp_push_front<mp_drop_c<L, I>, T...>>;
401
402Inserts the elements `T...` into the list `L` at position `I` (a zero-based index).
403
404.mp_insert_c with two elements
405[cols="<.^4m,8*^.^1m",width=85%]
406|===
407|*L1*|A~1~|...|A~m~|A~m+1~|...|A~n~ 2+|
4089+|
409|*mp_insert_c<L1, M, B~1~, B~2~>*|A~1~|...|A~m~|B~1~|B~2~|A~m+1~|...|A~n~
410|===
411
412## mp_insert<L, I, T...>
413
414    template<class L, class I, class... T> using mp_insert =
415        mp_append<mp_take<L, I>, mp_push_front<mp_drop<L, I>, T...>>;
416
417Same as `mp_insert_c`, but with a type argument `I`.
418
419## mp_erase_c<L, I, J>
420
421    template<class L, std::size_t I, std::size_t J> using mp_erase_c =
422        mp_append<mp_take_c<L, I>, mp_drop_c<L, J>>;
423
424Removes from the list `L` the elements with indices from `I` (inclusive) to `J` (exclusive).
425
426.mp_erase_c
427[cols="<.^4m,9*^.^1m",width=85%]
428|===
429|*L1*|A~0~|...|A~i-1~|A~i~|...|A~j-1~|A~j~|...|A~n-1~
43010+|
431|*mp_erase_c<L1, I, J>*|A~0~|...|A~i-1~|A~j~|...|A~n-1~ 3+|
432|===
433
434## mp_erase<L, I, J>
435
436    template<class L, class I, class J> using mp_erase =
437        mp_append<mp_take<L, I>, mp_drop<L, J>>;
438
439Same as `mp_erase_c`, but with a type arguments `I` and `J`.
440
441## mp_replace<L, V, W>
442
443    template<class L, class V, class W> using mp_replace = /*...*/;
444
445Replaces all `V` elements of `L` with `W` and returns the result.
446
447.mp_replace
448[cols="<.^4m,4*^.^1m",width=85%]
449|===
450|*L1*|A~1~|V|...|A~n~
4515+|
452|*mp_replace<L1, V, W>*|A~1~|W|...|A~n~
453|===
454
455## mp_replace_if<L, P, W>
456
457    template<class L, template<class...> class P, class W> using mp_replace_if = /*...*/;
458
459Replaces all `T` elements of `L` for which `mp_to_bool<P<T>>` is `mp_true` with `W` and returns the result.
460
461.mp_replace_if
462[cols="<.^4m,4*^.^1m",width=85%]
463|===
464|*L1*|A~1~|A~2~|...|A~n~
4655+|
466|*P<A~i~>*|mp_false|mp_true|...|mp_false
4675+|
468|*mp_replace_if<L1, P, W>*|A~1~|W|...|A~n~
469|===
470
471## mp_replace_if_q<L, Q, W>
472
473    template<class L, class Q, class W> using mp_replace_if_q =
474        mp_replace_if<L, Q::template fn, W>;
475
476As `mp_replace_if`, but takes a quoted metafunction.
477
478## mp_replace_at_c<L, I, W>
479
480    template<class L, std::size_t I, class W> using mp_replace_at_c = /*...*/;
481
482Replaces the element of `L` at zero-based index `I` with `W` and returns the result.
483
484## mp_replace_at<L, I, W>
485
486    template<class L, class I, class W> using mp_replace_at = /*...*/;
487
488Same as `mp_replace_at_c`, but with a type argument `I`. `I::value` must be a nonnegative number.
489
490## mp_rotate_left_c<L, N>
491
492    template<class L, std::size_t N> using mp_rotate_left_c = /*...*/;
493
494Moves the `N % M` initial elements of the list `L` to the back, where `M` is the size of `L`. Empty
495lists are unchanged.
496
497## mp_rotate_left<L, N>
498
499    template<class L, class N> using mp_rotate_left = /*...*/;
500
501Same as `mp_rotate_left_c`, but with a type argument `N`. `N::value` must be a nonnegative number.
502
503## mp_rotate_right_c<L, N>
504
505    template<class L, std::size_t N> using mp_rotate_right_c = /*...*/;
506
507Moves the `N % M` trailing elements of the list `L` to the front, where `M` is the size of `L`. Empty
508lists are unchanged.
509
510## mp_rotate_right<L, N>
511
512    template<class L, class N> using mp_rotate_right = /*...*/;
513
514Same as `mp_rotate_right_c`, but with a type argument `N`. `N::value` must be a nonnegative number.
515
516## mp_copy_if<L, P>
517
518    template<class L, template<class...> class P> using mp_copy_if = /*...*/;
519
520Copies the elements `T` of `L` for which `mp_to_bool<P<T>>` is `mp_true` to a new list of the same form and returns it.
521
522## mp_copy_if_q<L, Q>
523
524    template<class L, class Q> using mp_copy_if_q = mp_copy_if<L, Q::template fn>;
525
526As `mp_copy_if`, but takes a quoted metafunction.
527
528## mp_remove<L, V>
529
530    template<class L, class V> using mp_remove = /*...*/;
531
532Removes all `V` elements of `L` and returns the result.
533
534## mp_remove_if<L, P>
535
536    template<class L, template<class...> class P> using mp_remove_if = /*...*/;
537
538Removes all elements `T` of `L` for which `mp_to_bool<P<T>>` is `mp_true` and returns the result.
539
540## mp_remove_if_q<L, Q>
541
542    template<class L, class Q> using mp_remove_if_q = mp_remove_if<L, Q::template fn>;
543
544As `mp_remove_if`, but takes a quoted metafunction.
545
546## mp_flatten<L>
547
548    template<class L, class L2 = mp_clear<L>> using mp_flatten = /*...*/;
549
550Replaces all elements `T` of `L` that are lists of the same form as `L2` (that is, those for which
551`mp_similar<T, L2>` is `mp_true`) with their elements and returns the result.
552
553.Using mp_flatten
554```
555using L1 = tuple<int, tuple<>, void, tuple<float, double>>;
556using R1 = mp_flatten<L1>; // tuple<int, void, float, double>
557
558using L2 = mp_list<int, mp_list<float>, tuple<void>>;
559using R2a = mp_flatten<L2>; // mp_list<int, float, tuple<void>>
560using R2b = mp_flatten<L2, tuple<>>; // mp_list<int, mp_list<float>, void>
561
562using L3 = mp_list<mp_list<float>, mp_list<mp_list<void>>>;
563using R3 = mp_flatten<L3>; // mp_list<float, mp_list<void>>
564```
565
566## mp_partition<L, P>
567
568    template<class L, template<class...> class P> using mp_partition = /*...*/;
569
570`mp_partition<L<T...>, P>` partitions `L` into two lists `L<U1...>` and `L<U2...>` such that `mp_to_bool<P<T>>` is `mp_true`
571for the elements of `L<U1...>` and `mp_false` for the elements of `L<U2...>`. Returns `L<L<U1...>, L<U2...>>`.
572
573## mp_partition_q<L, Q>
574
575    template<class L, class Q> using mp_partition_q = mp_partition<L, Q::template fn>;
576
577As `mp_partition`, but takes a quoted metafunction.
578
579## mp_sort<L, P>
580
581    template<class L, template<class...> class P> using mp_sort = /*...*/;
582
583`mp_sort<L, P>` sorts the list `L` according to the strict weak ordering `mp_to_bool<P<T, U>>`.
584
585.Using mp_sort to sort a list of std::ratio values
586----
587#include <ratio>
588
589using L1 = mp_list<std::ratio<1,2>, std::ratio<1,4>>;
590using R1 = mp_sort<L1, std::ratio_less>; // mp_list<ratio<1,4>, ratio<1,2>>
591----
592
593## mp_sort_q<L, Q>
594
595    template<class L, class Q> using mp_sort_q = mp_sort<L, Q::template fn>;
596
597As `mp_sort`, but takes a quoted metafunction.
598
599## mp_nth_element_c<L, I, P>
600
601    template<class L, std::size_t I, template<class...> class P> using mp_nth_element_c =
602        /*...*/;
603
604Returns the element at position `I` in `mp_sort<L, P>`.
605
606## mp_nth_element<L, I, P>
607
608    template<class L, class I, template<class...> class P> using mp_nth_element = /*...*/;
609
610Like `mp_nth_element_c`, but with a type argument `I`. `I::value` must be a nonnegative number.
611
612## mp_nth_element_q<L, I, Q>
613
614    template<class L, class I, class Q> using mp_nth_element_q =
615        mp_nth_element<L, I, Q::template fn>;
616
617Like `mp_nth_element`, but takes a quoted metafunction.
618
619## mp_min_element<L, P>
620
621    template<class L, template<class...> class P> using mp_min_element = /*...*/;
622
623`mp_min_element<L, P>` returns the minimal element of the list `L` according to the ordering `mp_to_bool<P<T, U>>`.
624
625It's equivalent to `mp_fold<mp_rest<L>, mp_first<L>, F>`, where `F<T, U>` returns `mp_if<P<T, U>, T, U>`.
626
627## mp_min_element_q<L, Q>
628
629    template<class L, class Q> using mp_min_element_q = mp_min_element<L, Q::template fn>;
630
631As `mp_min_element`, but takes a quoted metafunction.
632
633## mp_max_element<L, P>
634
635    template<class L, template<class...> class P> using mp_max_element = /*...*/;
636
637`mp_max_element<L, P>` returns the maximal element of the list `L` according to the ordering `mp_to_bool<P<T, U>>`.
638
639It's equivalent to `mp_fold<mp_rest<L>, mp_first<L>, F>`, where `F<T, U>` returns `mp_if<P<U, T>, T, U>`.
640
641## mp_max_element_q<L, Q>
642
643    template<class L, class Q> using mp_max_element_q = mp_max_element<L, Q::template fn>;
644
645As `mp_max_element`, but takes a quoted metafunction.
646
647## mp_find<L, V>
648
649    template<class L, class V> using mp_find = /*...*/;
650
651`mp_find<L, V>` returns the index at which the type `V` is located in the list `L`. It's an alias for `mp_size_t<I>`,
652where `I` is the zero-based index of the first occurrence of `V` in `L`. If `L` does not contain `V`, `mp_find<L, V>`
653is `mp_size<L>`.
654
655## mp_find_if<L, P>
656
657    template<class L, template<class...> class P> using mp_find_if = /*...*/;
658
659`mp_find_f<L, P>` is an alias for `mp_size_t<I>`, where `I` is the zero-based index of the first element `T` in `L` for which
660`mp_to_bool<P<T>>` is `mp_true`. If there is no such element, `mp_find_if<L, P>` is `mp_size<L>`.
661
662## mp_find_if_q<L, Q>
663
664    template<class L, class Q> using mp_find_if_q = mp_find_if<L, Q::template fn>;
665
666As `mp_find_if`, but takes a quoted metafunction.
667
668## mp_reverse<L>
669
670    template<class L> using mp_reverse = /*...*/;
671
672`mp_reverse<L<T1, T2, ..., Tn>>` is `L<Tn, ..., T2, T1>`.
673
674.mp_reverse
675[cols="<.^4m,4*^.^1m",width=85%]
676|===
677|*L1*|A~1~|A~2~|...|A~n~
6785+|
679|*mp_reverse<L1>*|A~n~|A~n-1~|...|A~1~
680|===
681
682## mp_fold<L, V, F>
683
684    template<class L, class V, template<class...> class F> using mp_fold = /*...*/;
685
686`mp_fold<L<T1, T2, ..., Tn>, V, F>` is `F< F< F< F<V, T1>, T2>, ...>, Tn>`, or `V`, if `L` is empty.
687
688.Using mp_fold to add the contents of a list of std::ratio values
689----
690#include <ratio>
691
692using L1 = mp_list<std::ratio<1,8>, std::ratio<1,4>, std::ratio<1,2>>;
693using R1 = mp_fold<L1, std::ratio<0,1>, std::ratio_add>; // std::ratio<7,8>
694----
695
696## mp_fold_q<L, V, Q>
697
698    template<class L, class V, class Q> using mp_fold_q =
699        mp_fold<L, V, Q::template fn>;
700
701As `mp_fold`, but takes a quoted metafunction.
702
703## mp_reverse_fold<L, V, F>
704
705    template<class L, class V, template<class...> class F> using mp_reverse_fold =
706        /*...*/;
707
708`mp_reverse_fold<L<T1, T2, ..., Tn>, V, F>` is `F<T1, F<T2, F<..., F<Tn, V>>>>`, or `V`, if `L` is empty.
709
710## mp_reverse_fold_q<L, V, Q>
711
712    template<class L, class V, class Q> using mp_reverse_fold_q =
713        mp_reverse_fold<L, V, Q::template fn>;
714
715As `mp_reverse_fold`, but takes a quoted metafunction.
716
717## mp_partial_sum<L, V, F>
718
719    template<class L, class V, template<class...> class F> using mp_partial_sum = /*...*/;
720
721`mp_partial_sum<L, V, F>` is similar to `mp_fold<L, V, F>`, but instead of its final result, it returns
722a list (of the same form as `L`) holding the intermediate results of the fold. The last element of the
723result of `mp_partial_sum` is the same as the result of `mp_fold`.
724
725For example, `mp_fold<mp_list<X1, X2, X3>, V, F>` is `F<F<F<V, X1>, X2>, X3>`, but
726`mp_partial_sum<mp_list<X1, X2, X3>, V, F>` is `mp_list<F<V, X1>, F<F<V, X1>, X2>, F<F<F<V, X1>, X2>, X3>>`.
727
728It's common for `F` to be `mp_plus`, in which case the result contains the partial sums of `L`.
729
730.Using mp_partial_sum
731----
732using L1 = mp_list_c<int, 1, 2, 3, 4>;
733using R1 = mp_partial_sum<L1, mp_int<0>, mp_plus>; // mp_list_c<int, 1, 3, 6, 10>
734----
735
736## mp_partial_sum_q<L, V, Q>
737
738    template<class L, class V, class Q> using mp_partial_sum_q =
739        mp_partial_sum<L, V, Q::template fn>;
740
741As `mp_partial_sum`, but takes a quoted metafunction.
742
743## mp_iterate<V, F, R>
744
745    template<class V, template<class...> class F, template<class...> class R>
746        using mp_iterate = /*...*/;
747
748`mp_iterate<V, F, R>` applies `R` to `V` successively until that's no longer possible,
749yielding the sequence `V`, `R<V>`, `R<R<V>>`, `R<R<R<V>>>`...
750
751It then returns an `mp_list` whose elements are formed by applying `F` to the above
752sequence of values. That is, it returns `mp_list<F<V>, F<R<V>>, F<R<R<V>>>, ...>`.
753
754`mp_iterate` is in a way the reverse operation of `mp_reverse_fold`. Given
755
756    template<class T, class U> struct cons {};
757    struct nil {};
758
759`mp_reverse_fold<mp_list<X1, X2, X3>, nil, cons>` produces `cons<X1, cons<X2, cons<X3, nil>>>`,
760which when passed as `V` to `mp_iterate<V, mp_first, mp_second>` recovers the original
761`mp_list<X1, X2, X3>`.
762
763.Using mp_iterate
764----
765struct X1 {};
766struct X2 {};
767struct X3 {};
768
769using L1 = mp_list<X1, X2, X3>;
770using R1 = mp_iterate<L1, mp_first, mp_rest>; // L1
771
772template<class T, class U> struct cons {};
773struct nil {};
774
775using V2 = mp_reverse_fold<L1, nil, cons>; // cons<X1, cons<X2, cons<X3, nil>>>
776using R2 = mp_iterate<V2, mp_first, mp_second>; // L1
777
778struct Y1 {};
779struct Y2 { using value_type = double; using next_type = Y1; };
780struct Y3 { using value_type = float; using next_type = Y2; };
781struct Y4 { using value_type = int; using next_type = Y3; };
782
783template<class T> using value_type = typename T::value_type;
784template<class T> using next_type = typename T::next_type;
785
786using R3 = mp_iterate<Y4, mp_identity_t, next_type>; // mp_list<Y4, Y3, Y2, Y1>
787using R4 = mp_iterate<Y4, value_type, next_type>; // mp_list<int, float, double>
788----
789
790## mp_iterate_q<V, Qf, Qr>
791
792    template<class V, class Qf, class Qr> using mp_iterate_q =
793        mp_iterate<V, Qf::template fn, Qr::template fn>;
794
795As `mp_iterate`, but takes quoted metafunctions.
796
797## mp_unique<L>
798
799    template<class L> using mp_unique = /*...*/;
800
801`mp_unique<L>` returns a list of the same form as `L` with the duplicate elements removed.
802
803## mp_unique_if<L, P>
804
805    template<class L, template<class...> class P> using mp_unique_if = /*...*/;
806
807As `mp_unique`, but two elements `T` and `U` are considered duplicates when `mp_to_bool<P<T, U>>` is `mp_true`.
808
809## mp_unique_if_q<L, Q>
810
811    template<class L, class Q> using mp_unique_if_q =
812        mp_unique_if<L, Q::template fn>;
813
814As `mp_unique_if`, but takes a quoted metafunction.
815
816## mp_all_of<L, P>
817
818    template<class L, template<class...> class P> using mp_all_of =
819        mp_bool< mp_count_if<L, P>::value == mp_size<L>::value >;
820
821`mp_all_of<L, P>` is `mp_true` when `P` holds for all elements of `L`, `mp_false` otherwise. When `L` is empty, the result is `mp_true`.
822
823## mp_all_of_q<L, Q>
824
825    template<class L, class Q> using mp_all_of_q = mp_all_of<L, Q::template fn>;
826
827As `mp_all_of`, but takes a quoted metafunction.
828
829## mp_none_of<L, P>
830
831    template<class L, template<class...> class P> using mp_none_of =
832        mp_bool< mp_count_if<L, P>::value == 0 >;
833
834`mp_none_of<L, P>` is `mp_true` when `P` holds for no element of `L`, `mp_false` otherwise. When `L` is empty, the result is `mp_true`.
835
836## mp_none_of_q<L, Q>
837
838    template<class L, class Q> using mp_none_of_q = mp_none_of<L, Q::template fn>;
839
840As `mp_none_of`, but takes a quoted metafunction.
841
842## mp_any_of<L, P>
843
844    template<class L, template<class...> class P> using mp_any_of =
845        mp_bool< mp_count_if<L, P>::value != 0 >;
846
847`mp_any_of<L, P>` is `mp_true` when `P` holds for at least one element of `L`, `mp_false` otherwise. When `L` is empty, the result is `mp_false`.
848
849## mp_any_of_q<L, Q>
850
851    template<class L, class Q> using mp_any_of_q = mp_any_of<L, Q::template fn>;
852
853As `mp_any_of`, but takes a quoted metafunction.
854
855## mp_for_each<L>(f)
856
857    template<class L, class F> constexpr F mp_for_each(F&& f);
858
859`mp_for_each<L>(f)` calls `f` with `T()` for each element `T` of the list `L`, in order.
860
861Returns `std::forward<F>(f)`.
862
863.Using mp_for_each and a C++14 lambda to print a tuple
864```
865template<class... T> void print( std::tuple<T...> const & tp )
866{
867    std::size_t const N = sizeof...(T);
868
869    mp_for_each<mp_iota_c<N>>( [&]( auto I ){
870
871        // I is mp_size_t<0>, mp_size_t<1>, ..., mp_size_t<N-1>
872
873        std::cout << std::get<I>(tp) << std::endl;
874
875    });
876}
877```
878
879## mp_with_index<N>(i, f)
880
881    template<std::size_t N, class F>
882      constexpr auto mp_with_index( std::size_t i, F && f )
883        -> decltype(std::declval<F>()(std::declval<mp_size_t<0>>()));
884
885`mp_with_index<N>(i, f)` calls `f` with `mp_size_t<i>()` and returns the result. `i` must be less than `N`.
886Only `constexpr` on C++14 and higher.
887
888    template<class N, class F>
889      constexpr auto mp_with_index( std::size_t i, F && f )
890        -> decltype(std::declval<F>()(std::declval<mp_size_t<0>>()));
891
892Returns `mp_with_index<N::value>(i, f)`.
893
894.Using mp_with_index and a C++14 lambda to print the active element of a variant
895```
896template<class... T> void print( std::variant<T...> const& v )
897{
898    mp_with_index<sizeof...(T)>( v.index(), [&]( auto I ) {
899
900        // I is mp_size_t<v.index()>{} here
901
902        std::cout << std::get<I>( v ) << std::endl;
903
904    });
905}
906```
907