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