Horizon
meta.hpp
Go to the documentation of this file.
1 //
3 // Meta library
4 //
5 // Copyright Eric Niebler 2014-present
6 //
7 // Use, modification and distribution is subject to the
8 // Boost Software License, Version 1.0. (See accompanying
9 // file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
11 //
12 // Project home: https://github.com/ericniebler/meta
13 //
14 
15 #ifndef META_HPP
16 #define META_HPP
17 
18 #include <cstddef>
19 #include <initializer_list>
20 #include <meta/meta_fwd.hpp>
21 #include <type_traits>
22 #include <utility>
23 
24 #ifdef __clang__
25 #pragma GCC diagnostic push
26 #pragma GCC diagnostic ignored "-Wunknown-pragmas"
27 #pragma GCC diagnostic ignored "-Wpragmas"
28 #pragma GCC diagnostic ignored "-Wdocumentation-deprecated-sync"
29 #pragma GCC diagnostic ignored "-Wmissing-variable-declarations"
30 #endif
31 
35 
39 
43 
47 
51 
55 
59 
63 
67 
71 
74 
78 
82 
86 
89 
92 
95 
98 
101 
104 
107 
110 
113 
115 namespace meta
116 {
117  namespace detail
118  {
120  template <typename T>
121  constexpr T *_nullptr_v()
122  {
123  return nullptr;
124  }
125 
126 #if META_CXX_VARIABLE_TEMPLATES
127  template <typename T>
128  META_INLINE_VAR constexpr T *nullptr_v = nullptr;
129 #endif
130  } // namespace detail
131 
134  struct nil_
135  {
136  };
137 
140  template <META_TYPE_CONSTRAINT(trait) T>
141  using _t = typename T::type;
142 
143 #if META_CXX_VARIABLE_TEMPLATES || defined(META_DOXYGEN_INVOKED)
147  template <META_TYPE_CONSTRAINT(integral) T>
148  constexpr typename T::type::value_type _v = T::type::value;
149 #endif
150 
152  namespace lazy
153  {
156  template <typename T>
157  using _t = defer<_t, T>;
158  } // namespace lazy
159 
162  template <std::size_t N>
163  using size_t = std::integral_constant<std::size_t, N>;
164 
167  template <bool B>
168  using bool_ = std::integral_constant<bool, B>;
169 
172  template <int I>
173  using int_ = std::integral_constant<int, I>;
174 
177  template <char Ch>
178  using char_ = std::integral_constant<char, Ch>;
179 
181  // Math operations
184  template <META_TYPE_CONSTRAINT(integral) T>
185  using inc = std::integral_constant<decltype(T::type::value + 1), T::type::value + 1>;
186 
189  template <META_TYPE_CONSTRAINT(integral) T>
190  using dec = std::integral_constant<decltype(T::type::value - 1), T::type::value - 1>;
191 
195  template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
196  using plus = std::integral_constant<decltype(T::type::value + U::type::value),
197  T::type::value + U::type::value>;
198 
202  template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
203  using minus = std::integral_constant<decltype(T::type::value - U::type::value),
204  T::type::value - U::type::value>;
205 
209  template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
210  using multiplies = std::integral_constant<decltype(T::type::value * U::type::value),
211  T::type::value * U::type::value>;
212 
216  template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
217  using divides = std::integral_constant<decltype(T::type::value / U::type::value),
218  T::type::value / U::type::value>;
219 
223  template <META_TYPE_CONSTRAINT(integral) T>
224  using negate = std::integral_constant<decltype(-T::type::value), -T::type::value>;
225 
229  template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
230  using modulus = std::integral_constant<decltype(T::type::value % U::type::value),
231  T::type::value % U::type::value>;
232 
236  template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
238 
242  template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
244 
248  template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
249  using greater = bool_<(T::type::value > U::type::value)>;
250 
254  template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
255  using less = bool_<(T::type::value < U::type::value)>;
256 
260  template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
261  using greater_equal = bool_<(T::type::value >= U::type::value)>;
262 
266  template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
267  using less_equal = bool_<(T::type::value <= U::type::value)>;
268 
272  template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
273  using bit_and = std::integral_constant<decltype(T::type::value & U::type::value),
274  T::type::value & U::type::value>;
275 
279  template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
280  using bit_or = std::integral_constant<decltype(T::type::value | U::type::value),
281  T::type::value | U::type::value>;
282 
286  template <META_TYPE_CONSTRAINT(integral) T, META_TYPE_CONSTRAINT(integral) U>
287  using bit_xor = std::integral_constant<decltype(T::type::value ^ U::type::value),
288  T::type::value ^ U::type::value>;
289 
293  template <META_TYPE_CONSTRAINT(integral) T>
294  using bit_not = std::integral_constant<decltype(~T::type::value), ~T::type::value>;
295 
296  namespace lazy
297  {
300  template <typename T>
302 
305  template <typename T>
307 
310  template <typename T, typename U>
312 
315  template <typename T, typename U>
317 
320  template <typename T, typename U>
322 
325  template <typename T, typename U>
327 
330  template <typename T>
332 
335  template <typename T, typename U>
337 
340  template <typename T, typename U>
342 
345  template <typename T, typename U>
347 
350  template <typename T, typename U>
352 
355  template <typename T, typename U>
357 
360  template <typename T, typename U>
362 
365  template <typename T, typename U>
367 
370  template <typename T, typename U>
372 
375  template <typename T, typename U>
377 
380  template <typename T, typename U>
382 
385  template <typename T>
387  } // namespace lazy
388 
390  namespace detail
391  {
392  enum class indices_strategy_
393  {
394  done,
395  repeat,
396  recurse
397  };
398 
399  constexpr indices_strategy_ strategy_(std::size_t cur, std::size_t end)
400  {
401  return cur >= end ? indices_strategy_::done
402  : cur * 2 <= end ? indices_strategy_::repeat
403  : indices_strategy_::recurse;
404  }
405 
406  template <typename T>
407  constexpr std::size_t range_distance_(T begin, T end)
408  {
409  return begin <= end ? static_cast<std::size_t>(end - begin)
410  : throw "The start of the integer_sequence must not be "
411  "greater than the end";
412  }
413 
414  template <std::size_t End, typename State, indices_strategy_ Status_>
415  struct make_indices_
416  {
417  using type = State;
418  };
419 
420  template <typename T, T, typename>
421  struct coerce_indices_
422  {
423  };
424  } // namespace detail
426 
428  // integer_sequence
429 #if !META_CXX_INTEGER_SEQUENCE
432  template <typename T, T... Is>
434  {
435  using value_type = T;
437  static constexpr std::size_t size() noexcept { return sizeof...(Is); }
438  };
439 #endif
440 
442  // index_sequence
446  template <std::size_t... Is>
448 
449 #if META_HAS_MAKE_INTEGER_SEQ && !defined(META_DOXYGEN_INVOKED)
450  // Implement make_integer_sequence and make_index_sequence with the
451  // __make_integer_seq builtin on compilers that provide it. (Redirect
452  // through decltype to workaround suspected clang bug.)
454  namespace detail
455  {
456  template <typename T, T N>
457  __make_integer_seq<integer_sequence, T, N> make_integer_sequence_();
458  }
460 
461  template <typename T, T N>
462  using make_integer_sequence = decltype(detail::make_integer_sequence_<T, N>());
463 
464  template <std::size_t N>
465  using make_index_sequence = make_integer_sequence<std::size_t, N>;
466 #else
471  template <std::size_t N>
473  _t<detail::make_indices_<N, index_sequence<0>, detail::strategy_(1, N)>>;
474 
479  template <typename T, T N>
482 #endif
483 
485  // integer_range
490  template <typename T, T From, T To>
492  _t<detail::coerce_indices_<T, From,
493  make_index_sequence<detail::range_distance_(From, To)>>>;
494 
496  namespace detail
497  {
498  template <typename, typename>
499  struct concat_indices_
500  {
501  };
502 
503  template <std::size_t... Is, std::size_t... Js>
504  struct concat_indices_<index_sequence<Is...>, index_sequence<Js...>>
505  {
506  using type = index_sequence<Is..., (Js + sizeof...(Is))...>;
507  };
508 
509  template <>
510  struct make_indices_<0u, index_sequence<0>, indices_strategy_::done>
511  {
512  using type = index_sequence<>;
513  };
514 
515  template <std::size_t End, std::size_t... Values>
516  struct make_indices_<End, index_sequence<Values...>, indices_strategy_::repeat>
517  : make_indices_<End, index_sequence<Values..., (Values + sizeof...(Values))...>,
518  detail::strategy_(sizeof...(Values) * 2, End)>
519  {
520  };
521 
522  template <std::size_t End, std::size_t... Values>
523  struct make_indices_<End, index_sequence<Values...>, indices_strategy_::recurse>
524  : concat_indices_<index_sequence<Values...>,
525  make_index_sequence<End - sizeof...(Values)>>
526  {
527  };
528 
529  template <typename T, T Offset, std::size_t... Values>
530  struct coerce_indices_<T, Offset, index_sequence<Values...>>
531  {
532  using type =
533  integer_sequence<T, static_cast<T>(static_cast<T>(Values) + Offset)...>;
534  };
535  } // namespace detail
537 
540  template <META_TYPE_CONSTRAINT(invocable) Fn, typename... Args>
541  using invoke = typename Fn::template invoke<Args...>;
542 
544  namespace lazy
545  {
548  template <typename Fn, typename... Args>
549  using invoke = defer<invoke, Fn, Args...>;
550  } // namespace lazy
551 
556  template <typename T>
557  struct id
558  {
559 #if defined(META_WORKAROUND_CWG_1558) && !defined(META_DOXYGEN_INVOKED)
560  // Redirect through decltype for compilers that have not
561  // yet implemented CWG 1558:
562  static id impl(void *);
563 
564  template <typename... Ts>
565  using invoke = _t<decltype(id::impl(static_cast<list<Ts...> *>(nullptr)))>;
566 #else
567  template <typename...>
568  using invoke = T;
569 #endif
570 
571  using type = T;
572  };
573 
576  template <typename T>
577  using id_t = _t<id<T>>;
578 
579  namespace lazy
580  {
584  template <typename T>
585  using id = defer<id, T>;
586  } // namespace lazy
587 
590 #if defined(META_WORKAROUND_CWG_1558) && !defined(META_DOXYGEN_INVOKED)
591  // Redirect through decltype for compilers that have not
592  // yet implemented CWG 1558:
593  template <typename... Ts>
594  using void_ = invoke<id<void>, Ts...>;
595 #else
596  template <typename...>
597  using void_ = void;
598 #endif
599 
600 #if META_CXX_VARIABLE_TEMPLATES
601 #ifdef META_CONCEPT
604  template <typename T>
605  META_INLINE_VAR constexpr bool is_trait_v = trait<T>;
606 
609  template <typename T>
610  META_INLINE_VAR constexpr bool is_callable_v = invocable<T>;
611 #else // ^^^ Concepts / No concepts vvv
613  namespace detail
614  {
615  template <typename, typename = void>
616  META_INLINE_VAR constexpr bool is_trait_ = false;
617 
618  template <typename T>
619  META_INLINE_VAR constexpr bool is_trait_<T, void_<typename T::type>> = true;
620 
621  template <typename, typename = void>
622  META_INLINE_VAR constexpr bool is_callable_ = false;
623 
624  template <typename T>
625  META_INLINE_VAR constexpr bool is_callable_<T, void_<quote<T::template invoke>>> = true;
626  } // namespace detail
628 
631  template <typename T>
632  META_INLINE_VAR constexpr bool is_trait_v = detail::is_trait_<T>;
633 
636  template <typename T>
637  META_INLINE_VAR constexpr bool is_callable_v = detail::is_callable_<T>;
638 #endif // Concepts vs. variable templates
639 
643  template <typename T>
644  using is_trait = bool_<is_trait_v<T>>;
645 
649  template <typename T>
650  using is_callable = bool_<is_callable_v<T>>;
651 #else // ^^^ META_CXX_VARIABLE_TEMPLATES / !META_CXX_VARIABLE_TEMPLATES vvv
653  namespace detail
654  {
655  template <typename, typename = void>
656  struct is_trait_
657  {
658  using type = std::false_type;
659  };
660 
661  template <typename T>
662  struct is_trait_<T, void_<typename T::type>>
663  {
664  using type = std::true_type;
665  };
666 
667  template <typename, typename = void>
668  struct is_callable_
669  {
670  using type = std::false_type;
671  };
672 
673  template <typename T>
674  struct is_callable_<T, void_<quote<T::template invoke>>>
675  {
676  using type = std::true_type;
677  };
678  } // namespace detail
680 
681  template <typename T>
682  using is_trait = _t<detail::is_trait_<T>>;
683 
688  template <typename T>
690 #endif
691 
693  namespace detail
694  {
695 #ifdef META_CONCEPT
696  template <template <typename...> class, typename...>
697  struct defer_
698  {
699  };
700 
701  template <template <typename...> class C, typename... Ts>
702  requires valid<C, Ts...> struct defer_<C, Ts...>
703  {
704  using type = C<Ts...>;
705  };
706 
707  template <typename T, template <T...> class, T...>
708  struct defer_i_
709  {
710  };
711 
712  template <typename T, template <T...> class C, T... Is>
713  requires valid_i<T, C, Is...> struct defer_i_<T, C, Is...>
714  {
715  using type = C<Is...>;
716  };
717 #elif defined(META_WORKAROUND_MSVC_703656) // ^^^ Concepts / MSVC workaround vvv
718  template <typename, template <typename...> class, typename...>
719  struct _defer_
720  {
721  };
722 
723  template <template <typename...> class C, typename... Ts>
724  struct _defer_<void_<C<Ts...>>, C, Ts...>
725  {
726  using type = C<Ts...>;
727  };
728 
729  template <template <typename...> class C, typename... Ts>
730  using defer_ = _defer_<void, C, Ts...>;
731 
732  template <typename, typename T, template <T...> class, T...>
733  struct _defer_i_
734  {
735  };
736 
737  template <typename T, template <T...> class C, T... Is>
738  struct _defer_i_<void_<C<Is...>>, T, C, Is...>
739  {
740  using type = C<Is...>;
741  };
742 
743  template <typename T, template <T...> class C, T... Is>
744  using defer_i_ = _defer_i_<void, T, C, Is...>;
745 #else // ^^^ workaround ^^^ / vvv no workaround vvv
746  template <template <typename...> class C, typename... Ts,
747  template <typename...> class D = C>
748  id<D<Ts...>> try_defer_(int);
749  template <template <typename...> class C, typename... Ts>
750  nil_ try_defer_(long);
751 
752  template <template <typename...> class C, typename... Ts>
753  using defer_ = decltype(detail::try_defer_<C, Ts...>(0));
754 
755  template <typename T, template <T...> class C, T... Is, template <T...> class D = C>
756  id<D<Is...>> try_defer_i_(int);
757  template <typename T, template <T...> class C, T... Is>
758  nil_ try_defer_i_(long);
759 
760  template <typename T, template <T...> class C, T... Is>
761  using defer_i_ = decltype(detail::try_defer_i_<T, C, Is...>(0));
762 #endif // Concepts vs. MSVC vs. Other
763 
764  template <typename T>
765  using _t_t = _t<_t<T>>;
766  } // namespace detail
768 
770  // defer
785  template <template <typename...> class C, typename... Ts>
786  struct defer : detail::defer_<C, Ts...>
787  {
788  };
789 
791  // defer_i
796  template <typename T, template <T...> class C, T... Is>
797  struct defer_i : detail::defer_i_<T, C, Is...>
798  {
799  };
800 
802  // defer_trait
807  template <template <typename...> class C, typename... Ts>
808  using defer_trait = defer<detail::_t_t, detail::defer_<C, Ts...>>;
809 
811  // defer_trait_i
816  template <typename T, template <T...> class C, T... Is>
817  using defer_trait_i = defer<detail::_t_t, detail::defer_i_<T, C, Is...>>;
818 
823  template <typename T>
824  using sizeof_ = meta::size_t<sizeof(T)>;
825 
830  template <typename T>
831  using alignof_ = meta::size_t<alignof(T)>;
832 
833  namespace lazy
834  {
837  template <typename T>
839 
842  template <typename T>
844  } // namespace lazy
845 
846 #if META_CXX_VARIABLE_TEMPLATES
851  template <typename T, template <typename...> class C>
852  using is = bool_<is_v<T, C>>;
853 #else
856  namespace detail
857  {
858  template <typename, template <typename...> class>
859  struct is_ : std::false_type
860  {
861  };
862 
863  template <typename... Ts, template <typename...> class C>
864  struct is_<C<Ts...>, C> : std::true_type
865  {
866  };
867  } // namespace detail
869 
873  template <typename T, template <typename...> class C>
875 #endif
876 
879  template <META_TYPE_CONSTRAINT(invocable)... Fns>
880  struct compose_
881  {
882  };
883 
884  template <META_TYPE_CONSTRAINT(invocable) Fn0>
885  struct compose_<Fn0>
886  {
887  template <typename... Ts>
888  using invoke = invoke<Fn0, Ts...>;
889  };
890 
891  template <META_TYPE_CONSTRAINT(invocable) Fn0, META_TYPE_CONSTRAINT(invocable)... Fns>
892  struct compose_<Fn0, Fns...>
893  {
894  template <typename... Ts>
895  using invoke = invoke<Fn0, invoke<compose_<Fns...>, Ts...>>;
896  };
897 
898  template <typename... Fns>
899  using compose = compose_<Fns...>;
900 
901  namespace lazy
902  {
905  template <typename... Fns>
906  using compose = defer<compose, Fns...>;
907  } // namespace lazy
908 
911  template <template <typename...> class C>
912  struct quote
913  {
914  // Indirection through defer here needed to avoid Core issue 1430
915  // https://wg21.link/cwg1430
916  template <typename... Ts>
917  using invoke = _t<defer<C, Ts...>>;
918  };
919 
923  template <typename T, template <T...> class C>
924  struct quote_i
925  {
926  // Indirection through defer_i here needed to avoid Core issue 1430
927  // https://wg21.link/cwg1430
928  template <META_TYPE_CONSTRAINT(integral)... Ts>
929  using invoke = _t<defer_i<T, C, Ts::type::value...>>;
930  };
931 
932 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 8 && \
933 !defined(META_DOXYGEN_INVOKED)
934  template <template <typename...> class C>
935  struct quote_trait
936  {
937  template <typename... Ts>
938  using invoke = _t<invoke<quote<C>, Ts...>>;
939  };
940 
941  template <typename T, template <T...> class C>
942  struct quote_trait_i
943  {
944  template <typename... Ts>
945  using invoke = _t<invoke<quote_i<T, C>, Ts...>>;
946  };
947 #else
948  // clang-format off
954  template <template <typename...> class C>
956 
959  template <typename T, template <T...> class C>
961  // clang-format on
962 #endif
963 
967  template <META_TYPE_CONSTRAINT(invocable) Fn, typename... Ts>
968  struct bind_front
969  {
970  template <typename... Us>
971  using invoke = invoke<Fn, Ts..., Us...>;
972  };
973 
977  template <META_TYPE_CONSTRAINT(invocable) Fn, typename... Us>
978  struct bind_back
979  {
980  template <typename... Ts>
981  using invoke = invoke<Fn, Ts..., Us...>;
982  };
983 
984  namespace lazy
985  {
988  template <typename Fn, typename... Ts>
989  using bind_front = defer<bind_front, Fn, Ts...>;
990 
993  template <typename Fn, typename... Ts>
994  using bind_back = defer<bind_back, Fn, Ts...>;
995  } // namespace lazy
996 
998  namespace extension
999  {
1003  template <META_TYPE_CONSTRAINT(invocable) Fn, typename L>
1004  struct apply
1005  {
1006  };
1007 
1008  template <META_TYPE_CONSTRAINT(invocable) Fn, typename Ret, typename... Args>
1009  struct apply<Fn, Ret(Args...)> : lazy::invoke<Fn, Ret, Args...>
1010  {
1011  };
1012 
1013  template <META_TYPE_CONSTRAINT(invocable) Fn, template <typename...> class T,
1014  typename... Ts>
1015  struct apply<Fn, T<Ts...>> : lazy::invoke<Fn, Ts...>
1016  {
1017  };
1018 
1019  template <META_TYPE_CONSTRAINT(invocable) Fn, typename T, T... Is>
1020  struct apply<Fn, integer_sequence<T, Is...>>
1021  : lazy::invoke<Fn, std::integral_constant<T, Is>...>
1022  {
1023  };
1024  } // namespace extension
1025 
1029  template <META_TYPE_CONSTRAINT(invocable) Fn, typename L>
1031 
1032  namespace lazy
1033  {
1034  template <typename Fn, typename L>
1035  using apply = defer<apply, Fn, L>;
1036  }
1037 
1041  template <META_TYPE_CONSTRAINT(invocable) Fn,
1042  META_TYPE_CONSTRAINT(invocable) Q = quote<list>>
1044 
1048  template <META_TYPE_CONSTRAINT(invocable) Fn>
1050 
1051  namespace lazy
1052  {
1055  template <typename Fn, typename Q = quote<list>>
1057 
1060  template <typename Fn>
1062  } // namespace lazy
1063 
1066  template <META_TYPE_CONSTRAINT(invocable) Fn>
1067  struct flip
1068  {
1069  private:
1070  template <typename... Ts>
1071  struct impl
1072  {
1073  };
1074  template <typename A, typename B, typename... Ts>
1075  struct impl<A, B, Ts...> : lazy::invoke<Fn, B, A, Ts...>
1076  {
1077  };
1078 
1079  public:
1080  template <typename... Ts>
1081  using invoke = _t<impl<Ts...>>;
1082  };
1083 
1084  namespace lazy
1085  {
1088  template <typename Fn>
1090  } // namespace lazy
1091 
1093  namespace detail
1094  {
1095  template <typename...>
1096  struct on_
1097  {
1098  };
1099  template <typename Fn, typename... Gs>
1100  struct on_<Fn, Gs...>
1101  {
1102  template <typename... Ts>
1103  using invoke = invoke<Fn, invoke<compose<Gs...>, Ts>...>;
1104  };
1105  } // namespace detail
1107 
1111  template <META_TYPE_CONSTRAINT(invocable)... Fns>
1112  using on_ = detail::on_<Fns...>;
1113 
1114  template <typename... Fns>
1115  using on = on_<Fns...>;
1116 
1117  namespace lazy
1118  {
1121  template <typename Fn, typename G>
1123  } // namespace lazy
1124 
1126  // conditional_t
1128  namespace detail
1129  {
1130  template <bool>
1131  struct _cond
1132  {
1133  template <typename Then, typename Else>
1134  using invoke = Then;
1135  };
1136  template <>
1137  struct _cond<false>
1138  {
1139  template <typename Then, typename Else>
1140  using invoke = Else;
1141  };
1142  } // namespace detail
1144 
1147  template <bool If, typename Then, typename Else = void>
1149 
1151  // if_
1153  namespace detail
1154  {
1155 #ifdef META_CONCEPT
1156  template <typename...>
1157  struct _if_
1158  {
1159  };
1160 
1161  template <typename If>
1162  requires integral<If>
1163  struct _if_<If> : std::enable_if<_v<If>>
1164  {
1165  };
1166 
1167  template <typename If, typename Then>
1168  requires integral<If>
1169  struct _if_<If, Then> : std::enable_if<_v<If>, Then>
1170  {
1171  };
1172 
1173  template <typename If, typename Then, typename Else>
1174  requires integral<If>
1175  struct _if_<If, Then, Else> : std::conditional<_v<If>, Then, Else>
1176  {
1177  };
1178 #elif defined(__clang__)
1179  // Clang is faster with this implementation
1180  template <typename, typename = bool>
1181  struct _if_
1182  {
1183  };
1184 
1185  template <typename If>
1186  struct _if_<list<If>, decltype(bool(If::type::value))> : std::enable_if<If::type::value>
1187  {
1188  };
1189 
1190  template <typename If, typename Then>
1191  struct _if_<list<If, Then>, decltype(bool(If::type::value))>
1192  : std::enable_if<If::type::value, Then>
1193  {
1194  };
1195 
1196  template <typename If, typename Then, typename Else>
1197  struct _if_<list<If, Then, Else>, decltype(bool(If::type::value))>
1198  : std::conditional<If::type::value, Then, Else>
1199  {
1200  };
1201 #else
1202  // GCC seems to prefer this implementation
1203  template <typename, typename = std::true_type>
1204  struct _if_
1205  {
1206  };
1207 
1208  template <typename If>
1209  struct _if_<list<If>, bool_<If::type::value>>
1210  {
1211  using type = void;
1212  };
1213 
1214  template <typename If, typename Then>
1215  struct _if_<list<If, Then>, bool_<If::type::value>>
1216  {
1217  using type = Then;
1218  };
1219 
1220  template <typename If, typename Then, typename Else>
1221  struct _if_<list<If, Then, Else>, bool_<If::type::value>>
1222  {
1223  using type = Then;
1224  };
1225 
1226  template <typename If, typename Then, typename Else>
1227  struct _if_<list<If, Then, Else>, bool_<!If::type::value>>
1228  {
1229  using type = Else;
1230  };
1231 #endif
1232  } // namespace detail
1234 
1237 #ifdef META_CONCEPT
1238  template <typename... Args>
1239  using if_ = _t<detail::_if_<Args...>>;
1240 
1243  template <bool If, typename... Args>
1244  using if_c = _t<detail::_if_<bool_<If>, Args...>>;
1245 #else
1246  template <typename... Args>
1247  using if_ = _t<detail::_if_<list<Args...>>>;
1248 
1249  template <bool If, typename... Args>
1250  using if_c = _t<detail::_if_<list<bool_<If>, Args...>>>;
1251 #endif
1252 
1253  namespace lazy
1254  {
1257  template <typename... Args>
1258  using if_ = defer<if_, Args...>;
1259 
1262  template <bool If, typename... Args>
1263  using if_c = if_<bool_<If>, Args...>;
1264  } // namespace lazy
1265 
1267  namespace detail
1268  {
1269 #ifdef META_CONCEPT
1270  template <typename...>
1271  struct _and_
1272  {
1273  };
1274 
1275  template <>
1276  struct _and_<> : std::true_type
1277  {
1278  };
1279 
1280  template <typename B, typename... Bs>
1281  requires integral<B> && (bool(B::type::value))
1282  struct _and_<B, Bs...> : _and_<Bs...>
1283  {
1284  };
1285 
1286  template <typename B, typename... Bs>
1287  requires integral<B> && (!bool(B::type::value))
1288  struct _and_<B, Bs...> : std::false_type
1289  {
1290  };
1291 
1292  template <typename...>
1293  struct _or_
1294  {
1295  };
1296 
1297  template <>
1298  struct _or_<> : std::false_type
1299  {
1300  };
1301 
1302  template <typename B, typename... Bs>
1303  requires integral<B> && (bool(B::type::value))
1304  struct _or_<B, Bs...> : std::true_type
1305  {
1306  };
1307 
1308  template <typename B, typename... Bs>
1309  requires integral<B> && (!bool(B::type::value))
1310  struct _or_<B, Bs...> : _or_<Bs...>
1311  {
1312  };
1313 #else
1314  template <bool>
1315  struct _and_
1316  {
1317  template <typename...>
1318  using invoke = std::true_type;
1319  };
1320 
1321  template <>
1322  struct _and_<false>
1323  {
1324  template <typename B, typename... Bs>
1325  using invoke = invoke<
1326  if_c<!B::type::value, id<std::false_type>, _and_<0 == sizeof...(Bs)>>,
1327  Bs...>;
1328  };
1329 
1330  template <bool>
1331  struct _or_
1332  {
1333  template <typename = void>
1334  using invoke = std::false_type;
1335  };
1336 
1337  template <>
1338  struct _or_<false>
1339  {
1340  template <typename B, typename... Bs>
1341  using invoke = invoke<
1342  if_c<B::type::value, id<std::true_type>, _or_<0 == sizeof...(Bs)>>,
1343  Bs...>;
1344  };
1345 #endif
1346  } // namespace detail
1348 
1351  template <bool B>
1352  using not_c = bool_<!B>;
1353 
1356  template <META_TYPE_CONSTRAINT(integral) B>
1358 
1359 #if META_CXX_FOLD_EXPRESSIONS && !defined(META_WORKAROUND_GCC_UNKNOWN1)
1360  template <bool... Bs>
1361  META_INLINE_VAR constexpr bool and_v = (true && ... && Bs);
1362 
1365  template <bool... Bs>
1366 #if defined(META_WORKAROUND_MSVC_756112) || defined(META_WORKAROUND_GCC_86356)
1367  using and_c = bool_<and_v<Bs...>>;
1368 #else
1369  using and_c = bool_<(true && ... && Bs)>;
1370 #endif
1371 #else
1372 #if defined(META_WORKAROUND_GCC_66405)
1373  template <bool... Bs>
1374  using and_c = meta::bool_<
1377 #else
1378  template <bool... Bs>
1379  struct and_c
1380  : meta::bool_<
1381  META_IS_SAME(integer_sequence<bool, Bs...>,
1382  integer_sequence<bool, (Bs || true)...>)>
1383  {};
1384 #endif
1385 #if META_CXX_VARIABLE_TEMPLATES
1386  template <bool... Bs>
1387  META_INLINE_VAR constexpr bool and_v =
1388  META_IS_SAME(integer_sequence<bool, Bs...>,
1389  integer_sequence<bool, (Bs || true)...>);
1390 #endif
1391 #endif
1392 
1396  template <META_TYPE_CONSTRAINT(integral)... Bs>
1397  using strict_and_ = and_c<Bs::type::value...>;
1398 
1399  template <typename... Bs>
1400  using strict_and = strict_and_<Bs...>;
1401 
1405  template <typename... Bs>
1406 #ifdef META_CONCEPT
1407  using and_ = _t<detail::_and_<Bs...>>;
1408 #else
1409  // Make a trip through defer<> to avoid CWG1430
1410  // https://wg21.link/cwg1430
1411  using and_ = _t<defer<detail::_and_<0 == sizeof...(Bs)>::template invoke, Bs...>>;
1412 #endif
1413 
1416 #if META_CXX_FOLD_EXPRESSIONS && !defined(META_WORKAROUND_GCC_UNKNOWN1)
1417  template <bool... Bs>
1418  META_INLINE_VAR constexpr bool or_v = (false || ... || Bs);
1419 
1420  template <bool... Bs>
1421 #if defined(META_WORKAROUND_MSVC_756112) || defined(META_WORKAROUND_GCC_86356)
1422  using or_c = bool_<or_v<Bs...>>;
1423 #else
1424  using or_c = bool_<(false || ... || Bs)>;
1425 #endif
1426 #else
1427  template <bool... Bs>
1428  struct or_c
1429  : meta::bool_<
1430  !META_IS_SAME(integer_sequence<bool, Bs...>,
1431  integer_sequence<bool, (Bs && false)...>)>
1432  {};
1433 #if META_CXX_VARIABLE_TEMPLATES
1434  template <bool... Bs>
1435  META_INLINE_VAR constexpr bool or_v =
1436  !META_IS_SAME(integer_sequence<bool, Bs...>,
1437  integer_sequence<bool, (Bs && false)...>);
1438 #endif
1439 #endif
1440 
1444  template <META_TYPE_CONSTRAINT(integral)... Bs>
1445  using strict_or_ = or_c<Bs::type::value...>;
1446 
1447  template <typename... Bs>
1448  using strict_or = strict_or_<Bs...>;
1449 
1453  template <typename... Bs>
1454 #ifdef META_CONCEPT
1455  using or_ = _t<detail::_or_<Bs...>>;
1456 #else
1457  // Make a trip through defer<> to avoid CWG1430
1458  // https://wg21.link/cwg1430
1459  using or_ = _t<defer<detail::_or_<0 == sizeof...(Bs)>::template invoke, Bs...>>;
1460 #endif
1461 
1462  namespace lazy
1463  {
1466  template <typename... Bs>
1468 
1471  template <typename... Bs>
1473 
1476  template <typename B>
1478 
1481  template <typename... Bs>
1483 
1486  template <typename... Bs>
1488  } // namespace lazy
1489 
1491  // fold
1493  namespace detail
1494  {
1495  template <typename, typename, typename>
1496  struct fold_
1497  {
1498  };
1499 
1500  template <typename Fn, typename T0, typename T1, typename T2, typename T3, typename T4,
1501  typename T5, typename T6, typename T7, typename T8, typename T9>
1502  struct compose10_
1503  {
1504  template <typename X, typename Y>
1505  using F = invoke<Fn, X, Y>;
1506 
1507  template <typename S>
1508  using invoke =
1509  F<F<F<F<F<F<F<F<F<F<_t<S>, T0>, T1>, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>;
1510  };
1511 
1512 #ifdef META_CONCEPT
1513  template <typename Fn>
1514  struct compose_
1515  {
1516  template <typename X, typename Y>
1517  using F = invoke<Fn, X, Y>;
1518 
1519  template <typename T0, typename T1, typename T2, typename T3, typename T4,
1520  typename T5, typename T6, typename T7, typename T8, typename T9,
1521  typename State>
1522  using invoke =
1523  F<F<F<F<F<F<F<F<F<F<State, T0>, T1>, T2>, T3>, T4>, T5>, T6>, T7>, T8>, T9>;
1524  };
1525 
1526  template <typename State, typename Fn>
1527  struct fold_<list<>, State, Fn>
1528  {
1529  using type = State;
1530  };
1531 
1532  template <typename Head, typename... Tail, typename State, typename Fn>
1533  requires valid<invoke, Fn, State, Head>
1534  struct fold_<list<Head, Tail...>, State, Fn>
1535  : fold_<list<Tail...>, invoke<Fn, State, Head>, Fn>
1536  {
1537  };
1538 
1539  template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
1540  typename T6, typename T7, typename T8, typename T9, typename... Tail,
1541  typename State, typename Fn>
1542  requires valid<invoke, compose_<Fn>, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, State>
1543  struct fold_<list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Tail...>, State, Fn>
1544  : fold_<list<Tail...>,
1545  invoke<compose_<Fn>, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, State>, Fn>
1546  {
1547  };
1548 #else // ^^^ Concepts / no Concepts vvv
1549  template <typename Fn, typename T0>
1550  struct compose1_
1551  {
1552  template <typename X>
1553  using invoke = invoke<Fn, _t<X>, T0>;
1554  };
1555 
1556  template <typename State, typename Fn>
1557  struct fold_<list<>, State, Fn> : State
1558  {
1559  };
1560 
1561  template <typename Head, typename... Tail, typename State, typename Fn>
1562  struct fold_<list<Head, Tail...>, State, Fn>
1563  : fold_<list<Tail...>, lazy::invoke<compose1_<Fn, Head>, State>, Fn>
1564  {
1565  };
1566 
1567  template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
1568  typename T6, typename T7, typename T8, typename T9, typename... Tail,
1569  typename State, typename Fn>
1570  struct fold_<list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Tail...>, State, Fn>
1571  : fold_<list<Tail...>,
1572  lazy::invoke<compose10_<Fn, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>, State>, Fn>
1573  {
1574  };
1575 #endif // META_CONCEPT
1576  } // namespace detail
1578 
1585  template <META_TYPE_CONSTRAINT(list_like) L, typename State, META_TYPE_CONSTRAINT(invocable) Fn>
1586 #ifdef META_CONCEPT
1587  using fold = _t<detail::fold_<L, State, Fn>>;
1588 #else
1590 #endif
1591 
1596  template <META_TYPE_CONSTRAINT(list_like) L, typename State, META_TYPE_CONSTRAINT(invocable) Fn>
1598 
1599  namespace lazy
1600  {
1603  template <typename L, typename State, typename Fn>
1605 
1608  template <typename L, typename State, typename Fn>
1610  } // namespace lazy
1611 
1613  // reverse_fold
1615  namespace detail
1616  {
1617  template <typename, typename, typename>
1618  struct reverse_fold_
1619  {
1620  };
1621 
1622  template <typename State, typename Fn>
1623  struct reverse_fold_<list<>, State, Fn>
1624  {
1625  using type = State;
1626  };
1627 
1628 #ifdef META_CONCEPT
1629  template <typename Head, typename... L, typename State, typename Fn>
1630  requires trait<reverse_fold_<list<L...>, State, Fn>> struct reverse_fold_<
1631  list<Head, L...>, State, Fn>
1632  : lazy::invoke<Fn, _t<reverse_fold_<list<L...>, State, Fn>>, Head>
1633  {
1634  };
1635 #else
1636  template <typename Head, typename... Tail, typename State, typename Fn>
1637  struct reverse_fold_<list<Head, Tail...>, State, Fn>
1638  : lazy::invoke<compose1_<Fn, Head>, reverse_fold_<list<Tail...>, State, Fn>>
1639  {
1640  };
1641 #endif
1642 
1643  template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
1644  typename T6, typename T7, typename T8, typename T9, typename... Tail,
1645  typename State, typename Fn>
1646  struct reverse_fold_<list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Tail...>, State, Fn>
1647  : lazy::invoke<compose10_<Fn, T9, T8, T7, T6, T5, T4, T3, T2, T1, T0>,
1648  reverse_fold_<list<Tail...>, State, Fn>>
1649  {
1650  };
1651  } // namespace detail
1653 
1660  template <META_TYPE_CONSTRAINT(list_like) L, typename State, META_TYPE_CONSTRAINT(invocable) Fn>
1662 
1663  namespace lazy
1664  {
1667  template <typename L, typename State, typename Fn>
1669  } // namespace lazy
1670 
1672  // npos
1677 
1679  // list
1682  template <typename... Ts>
1683  struct list
1684  {
1685  using type = list;
1687  static constexpr std::size_t size() noexcept { return sizeof...(Ts); }
1688  };
1689 
1691  // size
1695  template <META_TYPE_CONSTRAINT(list_like) L>
1697 
1698  namespace lazy
1699  {
1702  template <typename L>
1704  } // namespace lazy
1705 
1707  // concat
1709  namespace detail
1710  {
1711  template <typename... Lists>
1712  struct concat_
1713  {
1714  };
1715 
1716  template <>
1717  struct concat_<>
1718  {
1719  using type = list<>;
1720  };
1721 
1722  template <typename... L1>
1723  struct concat_<list<L1...>>
1724  {
1725  using type = list<L1...>;
1726  };
1727 
1728  template <typename... L1, typename... L2>
1729  struct concat_<list<L1...>, list<L2...>>
1730  {
1731  using type = list<L1..., L2...>;
1732  };
1733 
1734  template <typename... L1, typename... L2, typename... L3>
1735  struct concat_<list<L1...>, list<L2...>, list<L3...>>
1736  {
1737  using type = list<L1..., L2..., L3...>;
1738  };
1739 
1740  template <typename... L1, typename... L2, typename... L3, typename... Rest>
1741  struct concat_<list<L1...>, list<L2...>, list<L3...>, Rest...>
1742  : concat_<list<L1..., L2..., L3...>, Rest...>
1743  {
1744  };
1745 
1746  template <typename... L1, typename... L2, typename... L3, typename... L4,
1747  typename... L5, typename... L6, typename... L7, typename... L8,
1748  typename... L9, typename... L10, typename... Rest>
1749  struct concat_<list<L1...>, list<L2...>, list<L3...>, list<L4...>, list<L5...>,
1750  list<L6...>, list<L7...>, list<L8...>, list<L9...>, list<L10...>,
1751  Rest...>
1752  : concat_<list<L1..., L2..., L3..., L4..., L5..., L6..., L7..., L8..., L9..., L10...>,
1753  Rest...>
1754  {
1755  };
1756  } // namespace detail
1758 
1764  template <META_TYPE_CONSTRAINT(list_like)... Ls>
1765  using concat_ = _t<detail::concat_<Ls...>>;
1766 
1767  template <typename... Lists>
1768  using concat = concat_<Lists...>;
1769 
1770  namespace lazy
1771  {
1774  template <typename... Lists>
1775  using concat = defer<concat, Lists...>;
1776  } // namespace lazy
1777 
1785  template <META_TYPE_CONSTRAINT(list_like) ListOfLists>
1786  using join = apply<quote<concat>, ListOfLists>;
1787 
1788  namespace lazy
1789  {
1792  template <typename ListOfLists>
1794  } // namespace lazy
1795 
1797  // transform
1799  namespace detail
1800  {
1801 #ifdef META_CONCEPT
1802  template <typename... Args>
1803  struct transform_
1804  {
1805  };
1806 
1807  template <typename... Ts, typename Fn>
1808  requires invocable<Fn> && and_v<valid<invoke, Fn, Ts>...>
1809  struct transform_<list<Ts...>, Fn>
1810  {
1811  using type = list<invoke<Fn, Ts>...>;
1812  };
1813 
1814  template <typename... Ts, typename... Us, typename Fn>
1815  requires invocable<Fn> && and_v<valid<invoke, Fn, Ts, Us>...>
1816  struct transform_<list<Ts...>, list<Us...>, Fn>
1817  {
1818  using type = list<invoke<Fn, Ts, Us>...>;
1819  };
1820 #else
1821  template <typename, typename = void>
1822  struct transform_
1823  {
1824  };
1825 
1826  template <typename... Ts, typename Fn>
1827  struct transform_<list<list<Ts...>, Fn>, void_<invoke<Fn, Ts>...>>
1828  {
1829  using type = list<invoke<Fn, Ts>...>;
1830  };
1831 
1832  template <typename... Ts0, typename... Ts1, typename Fn>
1833  struct transform_<list<list<Ts0...>, list<Ts1...>, Fn>,
1834  void_<invoke<Fn, Ts0, Ts1>...>>
1835  {
1836  using type = list<invoke<Fn, Ts0, Ts1>...>;
1837  };
1838 #endif
1839  } // namespace detail
1841 
1850 #ifdef META_CONCEPT
1851  template <typename... Args>
1852  using transform = _t<detail::transform_<Args...>>;
1853 #else
1854  template <typename... Args>
1855  using transform = _t<detail::transform_<list<Args...>>>;
1856 #endif
1857 
1858  namespace lazy
1859  {
1862  template <typename... Args>
1863  using transform = defer<transform, Args...>;
1864  } // namespace lazy
1865 
1867  // repeat_n
1869  namespace detail
1870  {
1871  template <typename T, std::size_t>
1872  using first_ = T;
1873 
1874  template <typename T, typename Ints>
1875  struct repeat_n_c_
1876  {
1877  };
1878 
1879  template <typename T, std::size_t... Is>
1880  struct repeat_n_c_<T, index_sequence<Is...>>
1881  {
1882  using type = list<first_<T, Is>...>;
1883  };
1884  } // namespace detail
1886 
1891  template <std::size_t N, typename T = void>
1893 
1898  template <META_TYPE_CONSTRAINT(integral) N, typename T = void>
1900 
1901  namespace lazy
1902  {
1905  template <typename N, typename T = void>
1907 
1910  template <std::size_t N, typename T = void>
1912  } // namespace lazy
1913 
1915  // at
1917  namespace detail
1918  {
1919 #if META_HAS_TYPE_PACK_ELEMENT && !defined(META_DOXYGEN_INVOKED)
1920  template <typename L, std::size_t N, typename = void>
1921  struct at_
1922  {
1923  };
1924 
1925  template <typename... Ts, std::size_t N>
1926  struct at_<list<Ts...>, N, void_<__type_pack_element<N, Ts...>>>
1927  {
1928  using type = __type_pack_element<N, Ts...>;
1929  };
1930 #else
1931  template <typename VoidPtrs>
1932  struct at_impl_;
1933 
1934  template <typename... VoidPtrs>
1935  struct at_impl_<list<VoidPtrs...>>
1936  {
1937  static nil_ eval(...);
1938 
1939  template <typename T, typename... Us>
1940  static T eval(VoidPtrs..., T *, Us *...);
1941  };
1942 
1943  template <typename L, std::size_t N>
1944  struct at_
1945  {
1946  };
1947 
1948  template <typename... Ts, std::size_t N>
1949  struct at_<list<Ts...>, N>
1950  : decltype(at_impl_<repeat_n_c<N, void *>>::eval(static_cast<id<Ts> *>(nullptr)...))
1951  {
1952  };
1953 #endif // META_HAS_TYPE_PACK_ELEMENT
1954  } // namespace detail
1956 
1961  template <META_TYPE_CONSTRAINT(list_like) L, std::size_t N>
1963 
1968  template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(integral) N>
1970 
1971  namespace lazy
1972  {
1975  template <typename L, typename N>
1977  } // namespace lazy
1978 
1980  // drop
1982  namespace detail
1983  {
1986  template <typename VoidPtrs>
1987  struct drop_impl_
1988  {
1989  static nil_ eval(...);
1990  };
1991 
1992  template <typename... VoidPtrs>
1993  struct drop_impl_<list<VoidPtrs...>>
1994  {
1995  static nil_ eval(...);
1996 
1997  template <typename... Ts>
1998  static id<list<Ts...>> eval(VoidPtrs..., id<Ts> *...);
1999  };
2000 
2001  template <>
2002  struct drop_impl_<list<>>
2003  {
2004  template <typename... Ts>
2005  static id<list<Ts...>> eval(id<Ts> *...);
2006  };
2007 
2008  template <typename L, std::size_t N>
2009  struct drop_
2010  {
2011  };
2012 
2013  template <typename... Ts, std::size_t N>
2014  struct drop_<list<Ts...>, N>
2015 #if META_CXX_VARIABLE_TEMPLATES
2016  : decltype(drop_impl_<repeat_n_c<N, void *>>::eval(detail::nullptr_v<id<Ts>>...))
2017 #else
2018  : decltype(drop_impl_<repeat_n_c<N, void *>>::eval(detail::_nullptr_v<id<Ts>>()...))
2019 #endif
2020  {
2021  };
2022  } // namespace detail
2024 
2029  template <META_TYPE_CONSTRAINT(list_like) L, std::size_t N>
2031 
2036  template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(integral) N>
2038 
2039  namespace lazy
2040  {
2043  template <typename L, typename N>
2045  } // namespace lazy
2046 
2048  // front
2050  namespace detail
2051  {
2052  template <typename L>
2053  struct front_
2054  {
2055  };
2056 
2057  template <typename Head, typename... Tail>
2058  struct front_<list<Head, Tail...>>
2059  {
2060  using type = Head;
2061  };
2062  } // namespace detail
2064 
2069  template <META_TYPE_CONSTRAINT(list_like) L>
2071 
2072  namespace lazy
2073  {
2076  template <typename L>
2078  } // namespace lazy
2079 
2081  // back
2083  namespace detail
2084  {
2085  template <typename L>
2086  struct back_
2087  {
2088  };
2089 
2090  template <typename Head, typename... Tail>
2091  struct back_<list<Head, Tail...>>
2092  {
2093  using type = at_c<list<Head, Tail...>, sizeof...(Tail)>;
2094  };
2095  } // namespace detail
2097 
2102  template <META_TYPE_CONSTRAINT(list_like) L>
2104 
2105  namespace lazy
2106  {
2109  template <typename L>
2111  } // namespace lazy
2112 
2114  // push_front
2119  template <META_TYPE_CONSTRAINT(list_like) L, typename... Ts>
2121 
2122  namespace lazy
2123  {
2126  template <typename... Ts>
2127  using push_front = defer<push_front, Ts...>;
2128  } // namespace lazy
2129 
2131  // pop_front
2133  namespace detail
2134  {
2135  template <typename L>
2136  struct pop_front_
2137  {
2138  };
2139 
2140  template <typename Head, typename... L>
2141  struct pop_front_<list<Head, L...>>
2142  {
2143  using type = list<L...>;
2144  };
2145  } // namespace detail
2147 
2153  template <META_TYPE_CONSTRAINT(list_like) L>
2155 
2156  namespace lazy
2157  {
2160  template <typename L>
2162  } // namespace lazy
2163 
2165  // push_back
2172  template <META_TYPE_CONSTRAINT(list_like) L, typename... Ts>
2174 
2175  namespace lazy
2176  {
2179  template <typename... Ts>
2180  using push_back = defer<push_back, Ts...>;
2181  } // namespace lazy
2182 
2184  namespace detail
2185  {
2186  template <typename T, typename U>
2187  using min_ = if_<less<U, T>, U, T>;
2188 
2189  template <typename T, typename U>
2190  using max_ = if_<less<U, T>, T, U>;
2191  } // namespace detail
2193 
2196  template <META_TYPE_CONSTRAINT(integral)... Ts>
2197  using min_ = fold<pop_front<list<Ts...>>, front<list<Ts...>>, quote<detail::min_>>;
2198 
2199  template <typename... Ts>
2200  using min = min_<Ts...>;
2201 
2204  template <META_TYPE_CONSTRAINT(integral)... Ts>
2205  using max_ = fold<pop_front<list<Ts...>>, front<list<Ts...>>, quote<detail::max_>>;
2206 
2207  template <typename... Ts>
2208  using max = max_<Ts...>;
2209 
2210  namespace lazy
2211  {
2214  template <typename... Ts>
2215  using min = defer<min, Ts...>;
2216 
2219  template <typename... Ts>
2220  using max = defer<max, Ts...>;
2221  } // namespace lazy
2222 
2224  // empty
2230  template <META_TYPE_CONSTRAINT(list_like) L>
2232 
2233  namespace lazy
2234  {
2237  template <typename L>
2239  } // namespace lazy
2240 
2242  // pair
2245  template <typename F, typename S>
2246  using pair = list<F, S>;
2247 
2250  template <typename Pair>
2252 
2255  template <typename Pair>
2257 
2258  namespace lazy
2259  {
2262  template <typename Pair>
2264 
2267  template <typename Pair>
2269  } // namespace lazy
2270 
2272  // find_index
2274  namespace detail
2275  {
2276  // With thanks to Peter Dimov:
2277  constexpr std::size_t find_index_i_(bool const *const first, bool const *const last,
2278  std::size_t N = 0)
2279  {
2280  return first == last ? npos::value
2281  : *first ? N : find_index_i_(first + 1, last, N + 1);
2282  }
2283 
2284  template <typename L, typename T>
2285  struct find_index_
2286  {
2287  };
2288 
2289  template <typename V>
2290  struct find_index_<list<>, V>
2291  {
2292  using type = npos;
2293  };
2294 
2295  template <typename... T, typename V>
2296  struct find_index_<list<T...>, V>
2297  {
2298 #ifdef META_WORKAROUND_LLVM_28385
2299  static constexpr bool s_v[sizeof...(T)] = {META_IS_SAME(T, V)...};
2300 #else
2301  static constexpr bool s_v[] = {META_IS_SAME(T, V)...};
2302 #endif
2303  using type = size_t<find_index_i_(s_v, s_v + sizeof...(T))>;
2304  };
2305  } // namespace detail
2307 
2314  template <META_TYPE_CONSTRAINT(list_like) L, typename T>
2316 
2317  namespace lazy
2318  {
2321  template <typename L, typename T>
2323  } // namespace lazy
2324 
2326  // reverse_find_index
2328  namespace detail
2329  {
2330  // With thanks to Peter Dimov:
2331  constexpr std::size_t reverse_find_index_i_(bool const *const first,
2332  bool const *const last, std::size_t N)
2333  {
2334  return first == last
2335  ? npos::value
2336  : *(last - 1) ? N - 1 : reverse_find_index_i_(first, last - 1, N - 1);
2337  }
2338 
2339  template <typename L, typename T>
2340  struct reverse_find_index_
2341  {
2342  };
2343 
2344  template <typename V>
2345  struct reverse_find_index_<list<>, V>
2346  {
2347  using type = npos;
2348  };
2349 
2350  template <typename... T, typename V>
2351  struct reverse_find_index_<list<T...>, V>
2352  {
2353 #ifdef META_WORKAROUND_LLVM_28385
2354  static constexpr bool s_v[sizeof...(T)] = {META_IS_SAME(T, V)...};
2355 #else
2356  static constexpr bool s_v[] = {META_IS_SAME(T, V)...};
2357 #endif
2358  using type = size_t<reverse_find_index_i_(s_v, s_v + sizeof...(T), sizeof...(T))>;
2359  };
2360  } // namespace detail
2362 
2369  template <META_TYPE_CONSTRAINT(list_like) L, typename T>
2371 
2372  namespace lazy
2373  {
2376  template <typename L, typename T>
2378  } // namespace lazy
2379 
2381  // find
2387  template <META_TYPE_CONSTRAINT(list_like) L, typename T>
2389 
2390  namespace lazy
2391  {
2394  template <typename L, typename T>
2396  } // namespace lazy
2397 
2399  // reverse_find
2401  namespace detail
2402  {
2403  template <typename L, typename T, typename State = list<>>
2404  struct reverse_find_
2405  {
2406  };
2407 
2408  template <typename T, typename State>
2409  struct reverse_find_<list<>, T, State>
2410  {
2411  using type = State;
2412  };
2413 
2414  template <typename Head, typename... L, typename T, typename State>
2415  struct reverse_find_<list<Head, L...>, T, State> : reverse_find_<list<L...>, T, State>
2416  {
2417  };
2418 
2419  template <typename... L, typename T, typename State>
2420  struct reverse_find_<list<T, L...>, T, State>
2421  : reverse_find_<list<L...>, T, list<T, L...>>
2422  {
2423  };
2424  } // namespace detail
2426 
2432  template <META_TYPE_CONSTRAINT(list_like) L, typename T>
2434 
2435  namespace lazy
2436  {
2439  template <typename L, typename T>
2441  } // namespace lazy
2442 
2444  // find_if
2446  namespace detail
2447  {
2448 #ifdef META_CONCEPT
2449  template <typename L, typename Fn>
2450  struct find_if_
2451  {
2452  };
2453 
2454  template <typename Fn>
2455  struct find_if_<list<>, Fn>
2456  {
2457  using type = list<>;
2458  };
2459 
2460  template <typename Head, typename... L, typename Fn>
2461  requires integral<invoke<Fn, Head>>
2462  struct find_if_<list<Head, L...>, Fn>
2463  : if_<invoke<Fn, Head>, id<list<Head, L...>>, find_if_<list<L...>, Fn>>
2464  {
2465  };
2466 #else
2467  constexpr bool const *find_if_i_(bool const *const begin, bool const *const end)
2468  {
2469  return begin == end || *begin ? begin : find_if_i_(begin + 1, end);
2470  }
2471 
2472  template <typename L, typename Fn, typename = void>
2473  struct find_if_
2474  {
2475  };
2476 
2477  template <typename Fn>
2478  struct find_if_<list<>, Fn>
2479  {
2480  using type = list<>;
2481  };
2482 
2483  template <typename... L, typename Fn>
2484  struct find_if_<list<L...>, Fn,
2485  void_<integer_sequence<bool, bool(invoke<Fn, L>::type::value)...>>>
2486  {
2487 #ifdef META_WORKAROUND_LLVM_28385
2488  static constexpr bool s_v[sizeof...(L)] = {invoke<Fn, L>::type::value...};
2489 #else
2490  static constexpr bool s_v[] = {invoke<Fn, L>::type::value...};
2491 #endif
2492  using type =
2493  drop_c<list<L...>, detail::find_if_i_(s_v, s_v + sizeof...(L)) - s_v>;
2494  };
2495 #endif
2496  } // namespace detail
2498 
2505  template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
2507 
2508  namespace lazy
2509  {
2512  template <typename L, typename Fn>
2514  } // namespace lazy
2515 
2517  // reverse_find_if
2519  namespace detail
2520  {
2521 #ifdef META_CONCEPT
2522  template <typename L, typename Fn, typename State = list<>>
2523  struct reverse_find_if_
2524  {
2525  };
2526 
2527  template <typename Fn, typename State>
2528  struct reverse_find_if_<list<>, Fn, State>
2529  {
2530  using type = State;
2531  };
2532 
2533  template <typename Head, typename... L, typename Fn, typename State>
2534  requires integral<invoke<Fn, Head>>
2535  struct reverse_find_if_<list<Head, L...>, Fn, State>
2536  : reverse_find_if_<list<L...>, Fn, if_<invoke<Fn, Head>, list<Head, L...>, State>>
2537  {
2538  };
2539 #else
2540  constexpr bool const *reverse_find_if_i_(bool const *const begin, bool const *const pos,
2541  bool const *const end)
2542  {
2543  return begin == pos
2544  ? end
2545  : *(pos - 1) ? pos - 1 : reverse_find_if_i_(begin, pos - 1, end);
2546  }
2547 
2548  template <typename L, typename Fn, typename = void>
2549  struct reverse_find_if_
2550  {
2551  };
2552 
2553  template <typename Fn>
2554  struct reverse_find_if_<list<>, Fn>
2555  {
2556  using type = list<>;
2557  };
2558 
2559  template <typename... L, typename Fn>
2560  struct reverse_find_if_<
2561  list<L...>, Fn,
2562  void_<integer_sequence<bool, bool(invoke<Fn, L>::type::value)...>>>
2563  {
2564 #ifdef META_WORKAROUND_LLVM_28385
2565  static constexpr bool s_v[sizeof...(L)] = {invoke<Fn, L>::type::value...};
2566 #else
2567  static constexpr bool s_v[] = {invoke<Fn, L>::type::value...};
2568 #endif
2569  using type =
2570  drop_c<list<L...>, detail::reverse_find_if_i_(s_v, s_v + sizeof...(L),
2571  s_v + sizeof...(L)) -
2572  s_v>;
2573  };
2574 #endif
2575  } // namespace detail
2577 
2584  template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
2586 
2587  namespace lazy
2588  {
2591  template <typename L, typename Fn>
2593  } // namespace lazy
2594 
2596  // replace
2598  namespace detail
2599  {
2600  template <typename L, typename T, typename U>
2601  struct replace_
2602  {
2603  };
2604 
2605  template <typename... L, typename T, typename U>
2606  struct replace_<list<L...>, T, U>
2607  {
2608  using type = list<if_c<META_IS_SAME(T, L), U, L>...>;
2609  };
2610  } // namespace detail
2612 
2618  template <META_TYPE_CONSTRAINT(list_like) L, typename T, typename U>
2620 
2621  namespace lazy
2622  {
2625  template <typename L, typename T, typename U>
2627  } // namespace lazy
2628 
2630  // replace_if
2632  namespace detail
2633  {
2634 #ifdef META_CONCEPT
2635  template <typename L, typename C, typename U>
2636  struct replace_if_
2637  {
2638  };
2639 
2640  template <typename... L, typename C, typename U>
2641  requires and_v<integral<invoke<C, L>>...>
2642  struct replace_if_<list<L...>, C, U>
2643  {
2644  using type = list<if_<invoke<C, L>, U, L>...>;
2645  };
2646 #else
2647  template <typename L, typename C, typename U, typename = void>
2648  struct replace_if_
2649  {
2650  };
2651 
2652  template <typename... L, typename C, typename U>
2653  struct replace_if_<list<L...>, C, U,
2654  void_<integer_sequence<bool, bool(invoke<C, L>::type::value)...>>>
2655  {
2656  using type = list<if_<invoke<C, L>, U, L>...>;
2657  };
2658 #endif
2659  } // namespace detail
2661 
2668  template <META_TYPE_CONSTRAINT(list_like) L, typename C, typename U>
2670 
2671  namespace lazy
2672  {
2675  template <typename L, typename C, typename U>
2677  } // namespace lazy
2678 
2680  // count
2681  namespace detail
2682  {
2683  template <typename, typename>
2684  struct count_
2685  {
2686  };
2687 
2688 #if (defined(META_CONCEPT) || META_CXX_VARIABLE_TEMPLATES) && META_CXX_FOLD_EXPRESSIONS
2689  template <typename... Ts, typename T>
2690  struct count_<list<Ts...>, T>
2691  {
2692  using type = meta::size_t<((std::size_t)META_IS_SAME(T, Ts) + ...)>;
2693  };
2694 #else
2695  constexpr std::size_t count_i_(bool const *const begin, bool const *const end,
2696  std::size_t n)
2697  {
2698  return begin == end ? n : detail::count_i_(begin + 1, end, n + *begin);
2699  }
2700 
2701  template <typename T>
2702  struct count_<list<>, T>
2703  {
2704  using type = meta::size_t<0>;
2705  };
2706 
2707  template <typename... L, typename T>
2708  struct count_<list<L...>, T>
2709  {
2710 #ifdef META_WORKAROUND_LLVM_28385
2711  static constexpr bool s_v[sizeof...(L)] = {META_IS_SAME(T, L)...};
2712 #else
2713  static constexpr bool s_v[] = {META_IS_SAME(T, L)...};
2714 #endif
2715  using type = meta::size_t<detail::count_i_(s_v, s_v + sizeof...(L), 0u)>;
2716  };
2717 #endif
2718  } // namespace detail
2719 
2724  template <META_TYPE_CONSTRAINT(list_like) L, typename T>
2726 
2727  namespace lazy
2728  {
2731  template <typename L, typename T>
2733  } // namespace lazy
2734 
2736  // count_if
2737  namespace detail
2738  {
2739 #if defined(META_CONCEPT) && META_CXX_FOLD_EXPRESSIONS
2740  template <typename, typename>
2741  struct count_if_
2742  {
2743  };
2744 
2745  template <typename... Ts, typename Fn>
2746  requires (integral<invoke<Fn, Ts>> && ...)
2747  struct count_if_<list<Ts...>, Fn>
2748  {
2749  using type = meta::size_t<((std::size_t)(bool)_v<invoke<Fn, Ts>> + ...)>;
2750  };
2751 #else
2752  template <typename L, typename Fn, typename = void>
2753  struct count_if_
2754  {
2755  };
2756 
2757  template <typename Fn>
2758  struct count_if_<list<>, Fn>
2759  {
2760  using type = meta::size_t<0>;
2761  };
2762 
2763  template <typename... L, typename Fn>
2764  struct count_if_<list<L...>, Fn,
2765  void_<integer_sequence<bool, bool(invoke<Fn, L>::type::value)...>>>
2766  {
2767 #if META_CXX_FOLD_EXPRESSIONS
2768  using type = meta::size_t<((std::size_t)(bool)invoke<Fn, L>::type::value + ...)>;
2769 #else
2770 #ifdef META_WORKAROUND_LLVM_28385
2771  static constexpr bool s_v[sizeof...(L)] = {invoke<Fn, L>::type::value...};
2772 #else
2773  static constexpr bool s_v[] = {invoke<Fn, L>::type::value...};
2774 #endif
2775  using type = meta::size_t<detail::count_i_(s_v, s_v + sizeof...(L), 0u)>;
2776 #endif // META_CXX_FOLD_EXPRESSIONS
2777  };
2778 #endif // META_CONCEPT
2779  } // namespace detail
2780 
2786  template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
2788 
2789  namespace lazy
2790  {
2793  template <typename L, typename Fn>
2795  } // namespace lazy
2796 
2798  // filter
2800  namespace detail
2801  {
2802  template <typename Pred>
2803  struct filter_
2804  {
2805  template <typename A>
2806  using invoke = if_c<invoke<Pred, A>::type::value, list<A>, list<>>;
2807  };
2808  } // namespace detail
2810 
2817  template <typename L, typename Pred>
2819 
2820  namespace lazy
2821  {
2824  template <typename L, typename Fn>
2826  } // namespace lazy
2827 
2829  // static_const
2831  namespace detail
2832  {
2833  template <typename T>
2834  struct static_const
2835  {
2836  static constexpr T value{};
2837  };
2838 
2839  // Avoid potential ODR violations with global objects:
2840  template <typename T>
2841  constexpr T static_const<T>::value;
2842  } // namespace detail
2843 
2845 
2847  // for_each
2849  namespace detail
2850  {
2851  struct for_each_fn
2852  {
2853  template <class Fn, class... Args>
2854  constexpr auto operator()(list<Args...>, Fn f) const -> Fn
2855  {
2856  return (void)std::initializer_list<int>{((void)f(Args{}), 0)...}, f;
2857  }
2858  };
2859  } // namespace detail
2861 
2862 #if META_CXX_INLINE_VARIABLES
2866  inline constexpr detail::for_each_fn for_each{};
2867 #else
2869  namespace
2870  {
2872 
2876  constexpr auto &&for_each = detail::static_const<detail::for_each_fn>::value;
2877 
2879  }
2881 #endif
2882 
2884  // transpose
2890  template <META_TYPE_CONSTRAINT(list_like) ListOfLists>
2893 
2894  namespace lazy
2895  {
2898  template <typename ListOfLists>
2900  } // namespace lazy
2901 
2903  // zip_with
2910  template <META_TYPE_CONSTRAINT(invocable) Fn, META_TYPE_CONSTRAINT(list_like) ListOfLists>
2912 
2913  namespace lazy
2914  {
2917  template <typename Fn, typename ListOfLists>
2919  } // namespace lazy
2920 
2922  // zip
2929  template <META_TYPE_CONSTRAINT(list_like) ListOfLists>
2931 
2932  namespace lazy
2933  {
2936  template <typename ListOfLists>
2938  } // namespace lazy
2939 
2941  // as_list
2943  namespace detail
2944  {
2945  template <typename T>
2946  using uncvref_t = _t<std::remove_cv<_t<std::remove_reference<T>>>>;
2947 
2948  // Indirection here needed to avoid Core issue 1430
2949  // https://wg21.link/cwg1430
2950  template <typename Sequence>
2951  struct as_list_ : lazy::invoke<uncurry<quote<list>>, Sequence>
2952  {
2953  };
2954  } // namespace detail
2956 
2960  template <typename Sequence>
2962 
2963  namespace lazy
2964  {
2967  template <typename Sequence>
2969  } // namespace lazy
2970 
2972  // reverse
2974  namespace detail
2975  {
2976  template <typename L, typename State = list<>>
2977  struct reverse_ : lazy::fold<L, State, quote<push_front>>
2978  {
2979  };
2980 
2981  template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5,
2982  typename T6, typename T7, typename T8, typename T9, typename... Ts,
2983  typename... Us>
2984  struct reverse_<list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Ts...>, list<Us...>>
2985  : reverse_<list<Ts...>, list<T9, T8, T7, T6, T5, T4, T3, T2, T1, T0, Us...>>
2986  {
2987  };
2988  }
2990 
2995  template <META_TYPE_CONSTRAINT(list_like) L>
2997 
2998  namespace lazy
2999  {
3002  template <typename L>
3004  } // namespace lazy
3005 
3008  template <META_TYPE_CONSTRAINT(invocable) Fn>
3010 
3011  namespace lazy
3012  {
3015  template <typename Fn>
3017  } // namespace lazy
3018 
3020  // all_of
3026  template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
3028 
3029  namespace lazy
3030  {
3033  template <typename L, typename Fn>
3035  } // namespace lazy
3036 
3038  // any_of
3044  template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
3046 
3047  namespace lazy
3048  {
3051  template <typename L, typename Fn>
3053  } // namespace lazy
3054 
3056  // none_of
3062  template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
3064 
3065  namespace lazy
3066  {
3069  template <typename L, META_TYPE_CONSTRAINT(invocable) Fn>
3071  } // namespace lazy
3072 
3074  // in
3080  template <META_TYPE_CONSTRAINT(list_like) L, typename T>
3082 
3083  namespace lazy
3084  {
3087  template <typename L, typename T>
3089  } // namespace lazy
3090 
3092  // inherit
3094  namespace detail
3095  {
3096  template <typename L>
3097  struct inherit_
3098  {
3099  };
3100 
3101  template <typename... L>
3102  struct inherit_<list<L...>> : L...
3103  {
3104  using type = inherit_;
3105  };
3106  } // namespace detail
3108 
3113  template <META_TYPE_CONSTRAINT(list_like) L>
3115 
3116  namespace lazy
3117  {
3120  template <typename L>
3122  } // namespace lazy
3123 
3125  // unique
3127  namespace detail
3128  {
3129  template <typename Set, typename T>
3130  struct in_
3131  {
3132  };
3133 
3134  template <typename... Set, typename T>
3135  struct in_<list<Set...>, T> : bool_<META_IS_BASE_OF(id<T>, inherit<list<id<Set>...>>)>
3136  {
3137  };
3138 
3139  template <typename Set, typename T>
3140  struct insert_back_
3141  {
3142  };
3143 
3144  template <typename... Set, typename T>
3145  struct insert_back_<list<Set...>, T>
3146  {
3147  using type = if_<in_<list<Set...>, T>, list<Set...>, list<Set..., T>>;
3148  };
3149  } // namespace detail
3151 
3156  template <META_TYPE_CONSTRAINT(list_like) L>
3158 
3159  namespace lazy
3160  {
3163  template <typename L>
3165  } // namespace lazy
3166 
3168  // partition
3170  namespace detail
3171  {
3172  template <typename Fn>
3173  struct partition_
3174  {
3175 #ifdef META_CONCEPT
3176  template <typename, typename>
3177 #else
3178  template <typename, typename, typename = void>
3179 #endif
3180  struct impl
3181  {
3182  };
3183  template <typename... Yes, typename... No, typename A>
3184 #ifdef META_CONCEPT
3185  requires integral<invoke<Fn, A>>
3186  struct impl<pair<list<Yes...>, list<No...>>, A>
3187 #else
3188  struct impl<pair<list<Yes...>, list<No...>>, A,
3189  void_<bool_<invoke<Fn, A>::type::value>>>
3190 #endif
3191  {
3192  using type = if_<meta::invoke<Fn, A>, pair<list<Yes..., A>, list<No...>>,
3193  pair<list<Yes...>, list<No..., A>>>;
3194  };
3195 
3196  template <typename State, typename A>
3197  using invoke = _t<impl<State, A>>;
3198  };
3199  } // namespace detail
3201 
3208  template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
3209  using partition = fold<L, pair<list<>, list<>>, detail::partition_<Fn>>;
3210 
3211  namespace lazy
3212  {
3215  template <typename L, typename Fn>
3217  } // namespace lazy
3218 
3220  // sort
3222  namespace detail
3223  {
3224  template <META_TYPE_CONSTRAINT(invocable) Fn, typename A, typename B, typename... Ts>
3225  using part_ = partition<list<B, Ts...>, bind_back<Fn, A>>;
3226 #ifdef META_CONCEPT
3227  template <typename L, typename Fn>
3228  requires list_like<L> && invocable<Fn>
3229 #else
3230  template <typename, typename, typename = void>
3231 #endif
3232  struct sort_
3233  {
3234  };
3235  template <typename Fn>
3236  struct sort_<list<>, Fn>
3237  {
3238  using type = list<>;
3239  };
3240 
3241  template <typename A, typename Fn>
3242  struct sort_<list<A>, Fn>
3243  {
3244  using type = list<A>;
3245  };
3246 
3247  template <typename A, typename B, typename... Ts, typename Fn>
3248 #ifdef META_CONCEPT
3249  requires trait<sort_<first<part_<Fn, A, B, Ts...>>, Fn>> &&
3250  trait<sort_<second<part_<Fn, A, B, Ts...>>, Fn>>
3251  struct sort_<list<A, B, Ts...>, Fn>
3252 #else
3253  struct sort_<
3254  list<A, B, Ts...>, Fn,
3255  void_<_t<sort_<first<part_<Fn, A, B, Ts...>>, Fn>>>>
3256 #endif
3257  {
3258  using P = part_<Fn, A, B, Ts...>;
3259  using type = concat<_t<sort_<first<P>, Fn>>, list<A>, _t<sort_<second<P>, Fn>>>;
3260  };
3261  } // namespace detail
3263 
3264  // clang-format off
3275  // clang-format on
3276  template <META_TYPE_CONSTRAINT(list_like) L, META_TYPE_CONSTRAINT(invocable) Fn>
3278 
3279  namespace lazy
3280  {
3283  template <typename L, typename Fn>
3285  } // namespace lazy
3286 
3288  // lambda_
3290  namespace detail
3291  {
3292  template <typename T, int = 0>
3293  struct protect_;
3294 
3295  template <typename, int = 0>
3296  struct vararg_;
3297 
3298  template <typename T, int = 0>
3299  struct is_valid_;
3300 
3301  // Returns which branch to evaluate
3302  template <typename If, typename... Ts>
3303 #ifdef META_CONCEPT
3304  using lazy_if_ = lazy::_t<defer<_if_, If, protect_<Ts>...>>;
3305 #else
3306  using lazy_if_ = lazy::_t<defer<_if_, list<If, protect_<Ts>...>>>;
3307 #endif
3308 
3309  template <typename A, typename T, typename Fn, typename Ts>
3310  struct subst1_
3311  {
3312  using type = list<list<T>>;
3313  };
3314  template <typename T, typename Fn, typename Ts>
3315  struct subst1_<Fn, T, Fn, Ts>
3316  {
3317  using type = list<>;
3318  };
3319  template <typename A, typename T, typename Fn, typename Ts>
3320  struct subst1_<vararg_<A>, T, Fn, Ts>
3321  {
3322  using type = list<Ts>;
3323  };
3324 
3325  template <typename As, typename Ts>
3326  using substitutions_ = push_back<
3327  join<transform<
3328  concat<As, repeat_n_c<size<Ts>{} + 2 - size<As>{}, back<As>>>,
3329  concat<Ts, repeat_n_c<2, back<As>>>,
3330  bind_back<quote_trait<subst1_>, back<As>, drop_c<Ts, size<As>{} - 2>>>>,
3331  list<back<As>>>;
3332 
3333 #if 0//def META_CONCEPT
3334  template <list_like As, list_like Ts>
3335  requires (_v<size<Ts>> + 2 >= _v<size<As>>)
3336  using substitutions = substitutions_<As, Ts>;
3337 #else // ^^^ concepts / no concepts vvv
3338  template <typename As, typename Ts>
3339  using substitutions =
3340 #ifdef META_WORKAROUND_MSVC_702792
3341  invoke<if_c<(size<Ts>::value + 2 >= size<As>::value), quote<substitutions_>>, As,
3342  Ts>;
3343 #else // ^^^ workaround ^^^ / vvv no workaround vvv
3344  invoke<if_c<(size<Ts>{} + 2 >= size<As>{}), quote<substitutions_>>, As, Ts>;
3345 #endif // META_WORKAROUND_MSVC_702792
3346 #endif // META_CONCEPT
3347 
3348  template <typename T>
3349  struct is_vararg_ : std::false_type
3350  {
3351  };
3352  template <typename T>
3353  struct is_vararg_<vararg_<T>> : std::true_type
3354  {
3355  };
3356 
3357  template <META_TYPE_CONSTRAINT(list_like) Tags>
3358  using is_variadic_ = is_vararg_<at<push_front<Tags, void>, dec<size<Tags>>>>;
3359 
3360  template <META_TYPE_CONSTRAINT(list_like) Tags, bool IsVariadic = is_variadic_<Tags>::value>
3361  struct lambda_;
3362 
3363  // Non-variadic lambda implementation
3364  template <typename... As>
3365  struct lambda_<list<As...>, false>
3366  {
3367  private:
3368  static constexpr std::size_t arity = sizeof...(As) - 1;
3369  using Tags = list<As...>; // Includes the lambda body as the last arg!
3370  using Fn = back<Tags>;
3371  template <typename T, META_TYPE_CONSTRAINT(list_like) Args>
3372  struct impl;
3373  template <typename T, META_TYPE_CONSTRAINT(list_like) Args>
3374  using lazy_impl_ = lazy::_t<defer<impl, T, protect_<Args>>>;
3375 #if 0//def META_CONCEPT
3376  template <typename, list_like>
3377 #else
3378  template <typename, typename, typename = void>
3379 #endif
3380  struct subst_
3381  {
3382  };
3383  template <template <typename...> class C, typename... Ts, typename Args>
3384 #if 0//def META_CONCEPT
3385  requires valid<C, _t<impl<Ts, Args>>...> struct subst_<defer<C, Ts...>, Args>
3386 #else
3387  struct subst_<defer<C, Ts...>, Args, void_<C<_t<impl<Ts, Args>>...>>>
3388 #endif
3389  {
3390  using type = C<_t<impl<Ts, Args>>...>;
3391  };
3392  template <typename T, template <T...> class C, T... Is, typename Args>
3393 #if 0//def META_CONCEPT
3394  requires valid_i<T, C, Is...> struct subst_<defer_i<T, C, Is...>, Args>
3395 #else
3396  struct subst_<defer_i<T, C, Is...>, Args, void_<C<Is...>>>
3397 #endif
3398  {
3399  using type = C<Is...>;
3400  };
3401  template <typename T, META_TYPE_CONSTRAINT(list_like) Args>
3402  struct impl : if_c<(reverse_find_index<Tags, T>() != npos()),
3403  lazy::at<Args, reverse_find_index<Tags, T>>, id<T>>
3404  {
3405  };
3406  template <typename T, typename Args>
3407  struct impl<protect_<T>, Args>
3408  {
3409  using type = T;
3410  };
3411  template <typename T, typename Args>
3412  struct impl<is_valid_<T>, Args>
3413  {
3414  using type = is_trait<impl<T, Args>>;
3415  };
3416  template <typename If, typename... Ts, typename Args>
3417  struct impl<defer<if_, If, Ts...>, Args> // Short-circuit if_
3418  : impl<lazy_impl_<lazy_if_<If, Ts...>, Args>, Args>
3419  {
3420  };
3421  template <typename B, typename... Bs, typename Args>
3422  struct impl<defer<and_, B, Bs...>, Args> // Short-circuit and_
3423  : impl<lazy_impl_<lazy_if_<B, lazy::and_<Bs...>, protect_<std::false_type>>, Args>,
3424  Args>
3425  {
3426  };
3427  template <typename B, typename... Bs, typename Args>
3428  struct impl<defer<or_, B, Bs...>, Args> // Short-circuit or_
3429  : impl<lazy_impl_<lazy_if_<B, protect_<std::true_type>, lazy::or_<Bs...>>, Args>,
3430  Args>
3431  {
3432  };
3433  template <template <typename...> class C, typename... Ts, typename Args>
3434  struct impl<defer<C, Ts...>, Args> : subst_<defer<C, Ts...>, Args>
3435  {
3436  };
3437  template <typename T, template <T...> class C, T... Is, typename Args>
3438  struct impl<defer_i<T, C, Is...>, Args> : subst_<defer_i<T, C, Is...>, Args>
3439  {
3440  };
3441  template <template <typename...> class C, typename... Ts, typename Args>
3442  struct impl<C<Ts...>, Args> : subst_<defer<C, Ts...>, Args>
3443  {
3444  };
3445  template <typename... Ts, typename Args>
3446  struct impl<lambda_<list<Ts...>, false>, Args>
3447  {
3448  using type = compose<uncurry<lambda_<list<As..., Ts...>, false>>,
3449  curry<bind_front<quote<concat>, Args>>>;
3450  };
3451  template <typename... Bs, typename Args>
3452  struct impl<lambda_<list<Bs...>, true>, Args>
3453  {
3454  using type = compose<typename lambda_<list<As..., Bs...>, true>::thunk,
3455  bind_front<quote<concat>, transform<Args, quote<list>>>,
3456  curry<bind_front<quote<substitutions>, list<Bs...>>>>;
3457  };
3458 
3459  public:
3460  template <typename... Ts>
3461 #ifdef META_CONCEPT
3462  requires (sizeof...(Ts) == arity) using invoke = _t<impl<Fn, list<Ts..., Fn>>>;
3463 #else
3464  using invoke = _t<if_c<sizeof...(Ts) == arity, impl<Fn, list<Ts..., Fn>>>>;
3465 #endif
3466  };
3467 
3468  // Lambda with variadic placeholder (broken out due to less efficient compile-time
3469  // resource usage)
3470  template <typename... As>
3471  struct lambda_<list<As...>, true>
3472  {
3473  private:
3474  template <META_TYPE_CONSTRAINT(list_like) T, bool IsVar>
3475  friend struct lambda_;
3476  using Tags = list<As...>; // Includes the lambda body as the last arg!
3477  template <typename T, META_TYPE_CONSTRAINT(list_like) Args>
3478  struct impl;
3479  template <META_TYPE_CONSTRAINT(list_like) Args>
3480  using eval_impl_ = bind_back<quote_trait<impl>, Args>;
3481  template <typename T, META_TYPE_CONSTRAINT(list_like) Args>
3482  using lazy_impl_ = lazy::_t<defer<impl, T, protect_<Args>>>;
3483  template <template <typename...> class C, META_TYPE_CONSTRAINT(list_like) Args,
3484  META_TYPE_CONSTRAINT(list_like) Ts>
3485  using try_subst_ = apply<quote<C>, join<transform<Ts, eval_impl_<Args>>>>;
3486 #if 0//def META_CONCEPT
3487  template <typename, list_like>
3488 #else
3489  template <typename, typename, typename = void>
3490 #endif
3491  struct subst_
3492  {
3493  };
3494  template <template <typename...> class C, typename... Ts, typename Args>
3495 #if 0//def META_CONCEPT
3496  requires is_true<try_subst_<C, Args, list<Ts...>>> struct subst_<defer<C, Ts...>, Args>
3497 #else
3498  struct subst_<defer<C, Ts...>, Args, void_<try_subst_<C, Args, list<Ts...>>>>
3499 #endif
3500  {
3501  using type = list<try_subst_<C, Args, list<Ts...>>>;
3502  };
3503  template <typename T, template <T...> class C, T... Is, typename Args>
3504 #if 0//def META_CONCEPT
3505  requires valid_i<T, C, Is...> struct subst_<defer_i<T, C, Is...>, Args>
3506 #else
3507  struct subst_<defer_i<T, C, Is...>, Args, void_<C<Is...>>>
3508 #endif
3509  {
3510  using type = list<C<Is...>>;
3511  };
3512  template <typename T, META_TYPE_CONSTRAINT(list_like) Args>
3513  struct impl : if_c<(reverse_find_index<Tags, T>() != npos()),
3514  lazy::at<Args, reverse_find_index<Tags, T>>, id<list<T>>>
3515  {
3516  };
3517  template <typename T, typename Args>
3518  struct impl<protect_<T>, Args>
3519  {
3520  using type = list<T>;
3521  };
3522  template <typename T, typename Args>
3523  struct impl<is_valid_<T>, Args>
3524  {
3525  using type = list<is_trait<impl<T, Args>>>;
3526  };
3527  template <typename If, typename... Ts, typename Args>
3528  struct impl<defer<if_, If, Ts...>, Args> // Short-circuit if_
3529  : impl<lazy_impl_<lazy_if_<If, Ts...>, Args>, Args>
3530  {
3531  };
3532  template <typename B, typename... Bs, typename Args>
3533  struct impl<defer<and_, B, Bs...>, Args> // Short-circuit and_
3534  : impl<lazy_impl_<lazy_if_<B, lazy::and_<Bs...>, protect_<std::false_type>>, Args>,
3535  Args>
3536  {
3537  };
3538  template <typename B, typename... Bs, typename Args>
3539  struct impl<defer<or_, B, Bs...>, Args> // Short-circuit or_
3540  : impl<lazy_impl_<lazy_if_<B, protect_<std::true_type>, lazy::or_<Bs...>>, Args>,
3541  Args>
3542  {
3543  };
3544  template <template <typename...> class C, typename... Ts, typename Args>
3545  struct impl<defer<C, Ts...>, Args> : subst_<defer<C, Ts...>, Args>
3546  {
3547  };
3548  template <typename T, template <T...> class C, T... Is, typename Args>
3549  struct impl<defer_i<T, C, Is...>, Args> : subst_<defer_i<T, C, Is...>, Args>
3550  {
3551  };
3552  template <template <typename...> class C, typename... Ts, typename Args>
3553  struct impl<C<Ts...>, Args> : subst_<defer<C, Ts...>, Args>
3554  {
3555  };
3556  template <typename... Bs, bool IsVar, typename Args>
3557  struct impl<lambda_<list<Bs...>, IsVar>, Args>
3558  {
3559  using type =
3560  list<compose<typename lambda_<list<As..., Bs...>, true>::thunk,
3561  bind_front<quote<concat>, Args>,
3562  curry<bind_front<quote<substitutions>, list<Bs...>>>>>;
3563  };
3564  struct thunk
3565  {
3566  template <typename S, typename R = _t<impl<back<Tags>, S>>>
3567 #ifdef META_CONCEPT
3568  requires (_v<size<R>> == 1) using invoke = front<R>;
3569 #else
3570  using invoke = if_c<size<R>{} == 1, front<R>>;
3571 #endif
3572  };
3573 
3574  public:
3575  template <typename... Ts>
3576  using invoke = invoke<thunk, substitutions<Tags, list<Ts...>>>;
3577  };
3578  } // namespace detail
3580 
3582  // lambda
3590  template <typename... Ts>
3591 #ifdef META_CONCEPT
3592  requires (sizeof...(Ts) > 0) using lambda = detail::lambda_<list<Ts...>>;
3593 #else
3594  using lambda = if_c<(sizeof...(Ts) > 0), detail::lambda_<list<Ts...>>>;
3595 #endif
3596 
3598  // is_valid
3601  template <typename T>
3602  using is_valid = detail::is_valid_<T>;
3603 
3605  // vararg
3607  template <typename T>
3608  using vararg = detail::vararg_<T>;
3609 
3611  // protect
3614  template <typename T>
3615  using protect = detail::protect_<T>;
3616 
3618  // var
3621  template <typename Tag, typename Value>
3622  struct var;
3623 
3625  namespace detail
3626  {
3627  template <typename...>
3628  struct let_
3629  {
3630  };
3631  template <typename Fn>
3632  struct let_<Fn>
3633  {
3634  using type = lazy::invoke<lambda<Fn>>;
3635  };
3636  template <typename Tag, typename Value, typename... Rest>
3637  struct let_<var<Tag, Value>, Rest...>
3638  {
3639  using type = lazy::invoke<lambda<Tag, _t<let_<Rest...>>>, Value>;
3640  };
3641  } // namespace detail
3643 
3659  template <typename... As>
3660  using let = _t<_t<detail::let_<As...>>>;
3661 
3662  namespace lazy
3663  {
3666  template <typename... As>
3667  using let = defer<let, As...>;
3668  } // namespace lazy
3669 
3670  // Some argument placeholders for use in \c lambda expressions.
3672  inline namespace placeholders
3673  {
3674  // regular placeholders:
3675  struct _a;
3676  struct _b;
3677  struct _c;
3678  struct _d;
3679  struct _e;
3680  struct _f;
3681  struct _g;
3682  struct _h;
3683  struct _i;
3684 
3685  // variadic placeholders:
3686  using _args = vararg<void>;
3687  using _args_a = vararg<_a>;
3688  using _args_b = vararg<_b>;
3689  using _args_c = vararg<_c>;
3690  } // namespace placeholders
3691 
3693  // cartesian_product
3695  namespace detail
3696  {
3697  template <typename M2, typename M>
3698  struct cartesian_product_fn
3699  {
3700  template <typename X>
3701  struct lambda0
3702  {
3703  template <typename Xs>
3704  using lambda1 = list<push_front<Xs, X>>;
3705  using type = join<transform<M2, quote<lambda1>>>;
3706  };
3707  using type = join<transform<M, quote_trait<lambda0>>>;
3708  };
3709  } // namespace detail
3711 
3718  template <META_TYPE_CONSTRAINT(list_like) ListOfLists>
3721 
3722  namespace lazy
3723  {
3726  template <typename ListOfLists>
3728  } // namespace lazy
3729 
3732  // add_const_if
3733  namespace detail
3734  {
3735  template <bool>
3736  struct add_const_if
3737  {
3738  template <typename T>
3739  using invoke = T const;
3740  };
3741  template <>
3742  struct add_const_if<false>
3743  {
3744  template <typename T>
3745  using invoke = T;
3746  };
3747  } // namespace detail
3748  template <bool If>
3749  using add_const_if_c = detail::add_const_if<If>;
3750  template <META_TYPE_CONSTRAINT(integral) If>
3751  using add_const_if = add_const_if_c<If::type::value>;
3753 
3756  // const_if
3757  template <bool If, typename T>
3758  using const_if_c = typename add_const_if_c<If>::template invoke<T>;
3759  template <typename If, typename T>
3760  using const_if = typename add_const_if<If>::template invoke<T>;
3762 
3764  namespace detail
3765  {
3766  template <typename State, typename Ch>
3767  using atoi_ = if_c<(Ch::value >= '0' && Ch::value <= '9'),
3768  std::integral_constant<typename State::value_type,
3769  State::value * 10 + (Ch::value - '0')>>;
3770  }
3772 
3773  inline namespace literals
3774  {
3777  template <char... Chs>
3778  constexpr fold<list<char_<Chs>...>, meta::size_t<0>, quote<detail::atoi_>>
3779  operator"" _z()
3780  {
3781  return {};
3782  }
3783  } // namespace literals
3784 } // namespace meta
3785 
3787 // Non-portable forward declarations of standard containers
3788 #ifndef META_NO_STD_FORWARD_DECLARATIONS
3789 #if defined(__apple_build_version__) || (defined(__clang__) && __clang_major__ < 6)
3790 META_BEGIN_NAMESPACE_STD
3791 META_BEGIN_NAMESPACE_VERSION
3792 template <class>
3793 class META_TEMPLATE_VIS allocator;
3794 template <class, class>
3795 struct META_TEMPLATE_VIS pair;
3796 template <class>
3797 struct META_TEMPLATE_VIS hash;
3798 template <class>
3799 struct META_TEMPLATE_VIS less;
3800 template <class>
3801 struct META_TEMPLATE_VIS equal_to;
3802 template <class>
3803 struct META_TEMPLATE_VIS char_traits;
3804 #if defined(_GLIBCXX_USE_CXX11_ABI) && _GLIBCXX_USE_CXX11_ABI
3805 inline namespace __cxx11 {
3806 #endif
3807 template <class, class, class>
3808 class META_TEMPLATE_VIS basic_string;
3809 #if defined(_GLIBCXX_USE_CXX11_ABI) && _GLIBCXX_USE_CXX11_ABI
3810 }
3811 #endif
3812 META_END_NAMESPACE_VERSION
3813 META_BEGIN_NAMESPACE_CONTAINER
3814 #if defined(__GLIBCXX__)
3815 inline namespace __cxx11 {
3816 #endif
3817 template <class, class>
3818 class META_TEMPLATE_VIS list;
3819 #if defined(__GLIBCXX__)
3820 }
3821 #endif
3822 template <class, class>
3823 class META_TEMPLATE_VIS forward_list;
3824 template <class, class>
3825 class META_TEMPLATE_VIS vector;
3826 template <class, class>
3827 class META_TEMPLATE_VIS deque;
3828 template <class, class, class, class>
3829 class META_TEMPLATE_VIS map;
3830 template <class, class, class, class>
3831 class META_TEMPLATE_VIS multimap;
3832 template <class, class, class>
3833 class META_TEMPLATE_VIS set;
3834 template <class, class, class>
3835 class META_TEMPLATE_VIS multiset;
3836 template <class, class, class, class, class>
3837 class META_TEMPLATE_VIS unordered_map;
3838 template <class, class, class, class, class>
3839 class META_TEMPLATE_VIS unordered_multimap;
3840 template <class, class, class, class>
3841 class META_TEMPLATE_VIS unordered_set;
3842 template <class, class, class, class>
3843 class META_TEMPLATE_VIS unordered_multiset;
3844 template <class, class>
3845 class META_TEMPLATE_VIS queue;
3846 template <class, class, class>
3847 class META_TEMPLATE_VIS priority_queue;
3848 template <class, class>
3849 class META_TEMPLATE_VIS stack;
3850 META_END_NAMESPACE_CONTAINER
3851 META_END_NAMESPACE_STD
3852 
3853 namespace meta
3854 {
3855  namespace detail
3856  {
3857  template <typename T, typename A = std::allocator<T>>
3858  using std_list = std::list<T, A>;
3859  template <typename T, typename A = std::allocator<T>>
3860  using std_forward_list = std::forward_list<T, A>;
3861  template <typename T, typename A = std::allocator<T>>
3862  using std_vector = std::vector<T, A>;
3863  template <typename T, typename A = std::allocator<T>>
3864  using std_deque = std::deque<T, A>;
3865  template <typename T, typename C = std::char_traits<T>, typename A = std::allocator<T>>
3866  using std_basic_string = std::basic_string<T, C, A>;
3867  template <typename K, typename V, typename C = std::less<K>,
3868  typename A = std::allocator<std::pair<K const, V>>>
3869  using std_map = std::map<K, V, C, A>;
3870  template <typename K, typename V, typename C = std::less<K>,
3871  typename A = std::allocator<std::pair<K const, V>>>
3872  using std_multimap = std::multimap<K, V, C, A>;
3873  template <typename K, typename C = std::less<K>, typename A = std::allocator<K>>
3874  using std_set = std::set<K, C, A>;
3875  template <typename K, typename C = std::less<K>, typename A = std::allocator<K>>
3876  using std_multiset = std::multiset<K, C, A>;
3877  template <typename K, typename V, typename H = std::hash<K>,
3878  typename C = std::equal_to<K>,
3879  typename A = std::allocator<std::pair<K const, V>>>
3880  using std_unordered_map = std::unordered_map<K, V, H, C, A>;
3881  template <typename K, typename V, typename H = std::hash<K>,
3882  typename C = std::equal_to<K>,
3883  typename A = std::allocator<std::pair<K const, V>>>
3884  using std_unordered_multimap = std::unordered_multimap<K, V, H, C, A>;
3885  template <typename K, typename H = std::hash<K>, typename C = std::equal_to<K>,
3886  typename A = std::allocator<K>>
3887  using std_unordered_set = std::unordered_set<K, H, C, A>;
3888  template <typename K, typename H = std::hash<K>, typename C = std::equal_to<K>,
3889  typename A = std::allocator<K>>
3890  using std_unordered_multiset = std::unordered_multiset<K, H, C, A>;
3891  template <typename T, typename C = std_deque<T>>
3892  using std_queue = std::queue<T, C>;
3893  template <typename T, typename C = std_vector<T>,
3894  class D = std::less<typename C::value_type>>
3895  using std_priority_queue = std::priority_queue<T, C, D>;
3896  template <typename T, typename C = std_deque<T>>
3897  using std_stack = std::stack<T, C>;
3898  } // namespace detail
3899 
3900  template <>
3901  struct quote<::std::list> : quote<detail::std_list>
3902  {
3903  };
3904  template <>
3905  struct quote<::std::deque> : quote<detail::std_deque>
3906  {
3907  };
3908  template <>
3909  struct quote<::std::forward_list> : quote<detail::std_forward_list>
3910  {
3911  };
3912  template <>
3913  struct quote<::std::vector> : quote<detail::std_vector>
3914  {
3915  };
3916  template <>
3917  struct quote<::std::basic_string> : quote<detail::std_basic_string>
3918  {
3919  };
3920  template <>
3921  struct quote<::std::map> : quote<detail::std_map>
3922  {
3923  };
3924  template <>
3925  struct quote<::std::multimap> : quote<detail::std_multimap>
3926  {
3927  };
3928  template <>
3929  struct quote<::std::set> : quote<detail::std_set>
3930  {
3931  };
3932  template <>
3933  struct quote<::std::multiset> : quote<detail::std_multiset>
3934  {
3935  };
3936  template <>
3937  struct quote<::std::unordered_map> : quote<detail::std_unordered_map>
3938  {
3939  };
3940  template <>
3941  struct quote<::std::unordered_multimap> : quote<detail::std_unordered_multimap>
3942  {
3943  };
3944  template <>
3945  struct quote<::std::unordered_set> : quote<detail::std_unordered_set>
3946  {
3947  };
3948  template <>
3949  struct quote<::std::unordered_multiset> : quote<detail::std_unordered_multiset>
3950  {
3951  };
3952  template <>
3953  struct quote<::std::queue> : quote<detail::std_queue>
3954  {
3955  };
3956  template <>
3957  struct quote<::std::priority_queue> : quote<detail::std_priority_queue>
3958  {
3959  };
3960  template <>
3961  struct quote<::std::stack> : quote<detail::std_stack>
3962  {
3963  };
3964 } // namespace meta
3965 
3966 #endif
3967 #endif
3969 
3970 #ifdef __clang__
3971 #pragma GCC diagnostic pop
3972 #endif
3973 #endif
CPP_concept is_true
\concept is_true
Definition: concepts.hpp:833
CPP_concept type
\concept type
Definition: concepts.hpp:838
compose< quote< _t >, quote_i< T, C > > quote_trait_i
Turn a trait template C taking literals of type T into an invocable.
Definition: meta.hpp:960
detail::on_< Fns... > on_
Use as on<Fn, Gs...>.
Definition: meta.hpp:1112
meta::_t< detail::inherit_< L > > inherit
A type that inherits from all the types in the list.
Definition: meta.hpp:3114
template(typename ActionFn, typename Rng)(concept(invocable_action_closure_)(ActionFn
\concept invocable_action_closure_
CPP_concept invocable
\concept invocable
Definition: concepts.hpp:48
_t< detail::make_indices_< N, index_sequence< 0 >, detail::strategy_(1, N)> > make_index_sequence
Generate index_sequence containing integer constants [0,1,2,...,N-1].
Definition: meta.hpp:473
std::integral_constant< char, Ch > char_
An integral constant wrapper for char.
Definition: meta.hpp:178
integer_sequence< std::size_t, Is... > index_sequence
A container for a sequence of compile-time integer constants of type std::size_t.
Definition: meta.hpp:447
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition: meta.hpp:168
std::integral_constant< std::size_t, N > size_t
An integral constant wrapper for std::size_t.
Definition: meta.hpp:163
_t< detail::coerce_indices_< T, From, make_index_sequence< detail::range_distance_(From, To)> >> integer_range
Makes the integer sequence [From, To).
Definition: meta.hpp:493
std::integral_constant< int, I > int_
An integral constant wrapper for int.
Definition: meta.hpp:173
_t< detail::coerce_indices_< T, 0, make_index_sequence< static_cast< std::size_t >(N)> >> make_integer_sequence
Generate integer_sequence containing integer constants [0,1,2,...,N-1].
Definition: meta.hpp:481
typename T::type _t
Type alias for T::type.
Definition: meta.hpp:141
_t< extension::apply< Fn, L > > apply
Applies the invocable Fn using the types in the type list L as arguments.
Definition: meta.hpp:1030
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition: meta.hpp:541
defer< bind_front, Fn, Ts... > bind_front
Definition: meta.hpp:989
defer< compose, Fns... > compose
Definition: meta.hpp:906
defer< uncurry, Fn > uncurry
Definition: meta.hpp:1061
defer< bind_back, Fn, Ts... > bind_back
Definition: meta.hpp:994
defer< _t, T > _t
Definition: meta.hpp:157
defer< invoke, Fn, Args... > invoke
Definition: meta.hpp:549
defer< second, Pair > second
Definition: meta.hpp:2268
defer< front, L > front
Definition: meta.hpp:2077
defer< size, L > size
Definition: meta.hpp:1703
defer< first, Pair > first
Definition: meta.hpp:2263
defer< if_, Args... > if_
Definition: meta.hpp:1258
defer< or_, Bs... > or_
Definition: meta.hpp:1472
defer< and_, Bs... > and_
Definition: meta.hpp:1467
if_< bool_< If >, Args... > if_c
Definition: meta.hpp:1263
defer< equal_to, T, U > equal_to
Definition: meta.hpp:341
defer< min, Ts... > min
Definition: meta.hpp:2215
defer< max, Ts... > max
Definition: meta.hpp:2220
defer< less, T, U > less
Definition: meta.hpp:356
defer< let, As... > let
Definition: meta.hpp:3667
defer< join, ListOfLists > join
Definition: meta.hpp:1793
defer< push_front, Ts... > push_front
Definition: meta.hpp:2127
defer< transform, Args... > transform
Definition: meta.hpp:1863
defer< concat, Lists... > concat
Definition: meta.hpp:1775
defer< fold, L, State, Fn > fold
Definition: meta.hpp:1604
defer< push_back, Ts... > push_back
Definition: meta.hpp:2180
_t< detail::at_< L, N > > at_c
Return the N th element in the meta::list L.
Definition: meta.hpp:1962
_t< detail::repeat_n_c_< T, make_index_sequence< N > >> repeat_n_c
Generate list<T,T,T...T> of size N arguments.
Definition: meta.hpp:1892
front< Pair > first
Retrieve the first element of the pair Pair.
Definition: meta.hpp:2251
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition: meta.hpp:1696
_t< detail::back_< L > > back
Return the last element in meta::list L.
Definition: meta.hpp:2103
at_c< L, N::type::value > at
Return the N th element in the meta::list L.
Definition: meta.hpp:1969
front< pop_front< Pair > > second
Retrieve the first element of the pair Pair.
Definition: meta.hpp:2256
repeat_n_c< N::type::value, T > repeat_n
Generate list<T,T,T...T> of size N arguments.
Definition: meta.hpp:1899
meta::size_t< std::size_t(-1)> npos
A special value used to indicate no matches.
Definition: meta.hpp:1676
_t< detail::front_< L > > front
Return the first element in meta::list L.
Definition: meta.hpp:2070
bool_< 0==size< L >::type::value > empty
An Boolean integral constant wrapper around true if L is an empty type list; false,...
Definition: meta.hpp:2231
_t< detail::as_list_< detail::uncvref_t< Sequence > >> as_list
Turn a type into an instance of meta::list in a way determined by meta::apply.
Definition: meta.hpp:2961
list< F, S > pair
A list with exactly two elements.
Definition: meta.hpp:2246
_t< defer< detail::_or_< 0==sizeof...(Bs)>::template invoke, Bs... > > or_
Logically OR together all the integral constant-wrapped Boolean parameters, with short-circuiting.
Definition: meta.hpp:1459
_t< detail::_if_< list< Args... > >> if_
Select one type or another depending on a compile-time Boolean.
Definition: meta.hpp:1247
not_c< B::type::value > not_
Logically negate the integral constant-wrapped Boolean parameter.
Definition: meta.hpp:1357
typename detail::_cond< If >::template invoke< Then, Else > conditional_t
Select one type or another depending on a compile-time Boolean.
Definition: meta.hpp:1148
bool_<!B > not_c
Logically negate the Boolean parameter.
Definition: meta.hpp:1352
_t< defer< detail::_and_< 0==sizeof...(Bs)>::template invoke, Bs... > > and_
Logically AND together all the integral constant-wrapped Boolean parameters, with short-circuiting.
Definition: meta.hpp:1411
bool_<(T::type::value >=U::type::value)> greater_equal
A Boolean integral constant wrapper around true if T::type::value is greater than or equal to U::type...
Definition: meta.hpp:261
fold< pop_front< list< Ts... > >, front< list< Ts... > >, quote< detail::min_ > > min_
An integral constant wrapper around the minimum of Ts::type::value...
Definition: meta.hpp:2197
bool_< T::type::value !=U::type::value > not_equal_to
A Boolean integral constant wrapper around the result of comparing T::type::value and U::type::value ...
Definition: meta.hpp:243
std::integral_constant< decltype(T::type::value ^ U::type::value), T::type::value ^ U::type::value > bit_xor
An integral constant wrapper around the result of bitwise-exclusive-or'ing the two wrapped integers T...
Definition: meta.hpp:288
std::integral_constant< decltype(T::type::value &U::type::value), T::type::value &U::type::value > bit_and
An integral constant wrapper around the result of bitwise-and'ing the two wrapped integers T::type::v...
Definition: meta.hpp:274
std::integral_constant< decltype(T::type::value/U::type::value), T::type::value/U::type::value > divides
An integral constant wrapper around the result of dividing the two wrapped integers T::type::value an...
Definition: meta.hpp:218
std::integral_constant< decltype(T::type::value - U::type::value), T::type::value - U::type::value > minus
An integral constant wrapper around the result of subtracting the two wrapped integers T::type::value...
Definition: meta.hpp:204
std::integral_constant< decltype(T::type::value|U::type::value), T::type::value|U::type::value > bit_or
An integral constant wrapper around the result of bitwise-or'ing the two wrapped integers T::type::va...
Definition: meta.hpp:281
std::integral_constant< decltype(~T::type::value), ~T::type::value > bit_not
An integral constant wrapper around the result of bitwise-complementing the wrapped integer T::type::...
Definition: meta.hpp:294
std::integral_constant< decltype(T::type::value *U::type::value), T::type::value *U::type::value > multiplies
An integral constant wrapper around the result of multiplying the two wrapped integers T::type::value...
Definition: meta.hpp:211
std::integral_constant< decltype(-T::type::value), -T::type::value > negate
An integral constant wrapper around the result of negating the wrapped integer T::type::value.
Definition: meta.hpp:224
bool_<(T::type::value<=U::type::value)> less_equal
A Boolean integral constant wrapper around true if T::type::value is less than or equal to U::type::v...
Definition: meta.hpp:267
std::integral_constant< decltype(T::type::value+U::type::value), T::type::value+U::type::value > plus
An integral constant wrapper around the result of adding the two wrapped integers T::type::value and ...
Definition: meta.hpp:197
bool_<(T::type::value< U::type::value)> less
A Boolean integral constant wrapper around true if T::type::value is less than U::type::value; false,...
Definition: meta.hpp:255
std::integral_constant< decltype(T::type::value % U::type::value), T::type::value % U::type::value > modulus
An integral constant wrapper around the remainder of dividing the two wrapped integers T::type::value...
Definition: meta.hpp:231
bool_< T::type::value==U::type::value > equal_to
A Boolean integral constant wrapper around the result of comparing T::type::value and U::type::value ...
Definition: meta.hpp:237
bool_<(T::type::value > U::type::value)> greater
A Boolean integral constant wrapper around true if T::type::value is greater than U::type::value; fal...
Definition: meta.hpp:249
fold< pop_front< list< Ts... > >, front< list< Ts... > >, quote< detail::max_ > > max_
An integral constant wrapper around the maximum of Ts::type::value...
Definition: meta.hpp:2205
empty< find_if< L, Fn > > none_of
A Boolean integral constant wrapper around true if invoke<Fn, A>::value is false for all elements A i...
Definition: meta.hpp:3063
not_< empty< find_if< L, Fn > >> any_of
A Boolean integral constant wrapper around true if invoke<Fn, A>::value is true for any element A in ...
Definition: meta.hpp:3045
drop< L, min< find_index< L, T >, size< L > >> find
Return the tail of the list L starting at the first occurrence of T, if any such element exists; the ...
Definition: meta.hpp:2388
_t< detail::find_index_< L, T > > find_index
Finds the index of the first occurrence of the type T within the list L.
Definition: meta.hpp:2315
_t< detail::count_if_< L, Fn > > count_if
Count the number of times the predicate Fn evaluates to true for all the elements in the list L.
Definition: meta.hpp:2787
_t< detail::reverse_find_index_< L, T > > reverse_find_index
Finds the index of the last occurrence of the type T within the list L.
Definition: meta.hpp:2370
not_< empty< find< L, T > >> in
A Boolean integral constant wrapper around true if there is at least one occurrence of T in L.
Definition: meta.hpp:3081
_t< detail::count_< L, T > > count
Count the number of times a type T appears in the list L.
Definition: meta.hpp:2725
_t< detail::reverse_find_if_< L, Fn > > reverse_find_if
Return the tail of the list L starting at the last element A such that invoke<Fn, A>::value is true,...
Definition: meta.hpp:2585
empty< find_if< L, not_fn< Fn > >> all_of
A Boolean integral constant wrapper around true if invoke<Fn, A>::value is true for all elements A in...
Definition: meta.hpp:3027
_t< detail::find_if_< L, Fn > > find_if
Return the tail of the list L starting at the first element A such that invoke<Fn,...
Definition: meta.hpp:2506
drop< L, min< reverse_find_index< L, T >, size< L > >> reverse_find
Return the tail of the list L starting at the last occurrence of T, if any such element exists; the e...
Definition: meta.hpp:2433
constexpr auto && for_each
for_each(List, UnaryFunction) calls the UnaryFunction for each argument in the List.
Definition: meta.hpp:2876
detail::is_valid_< T > is_valid
For testing whether a deferred computation will succeed in a let or a lambda.
Definition: meta.hpp:3602
_t< detail::is_callable_< T > > is_callable
An alias for std::true_type if T::invoke exists and names a class template or alias template; otherwi...
Definition: meta.hpp:689
_t< detail::is_< T, C > > is
is
Definition: meta.hpp:874
_t< _t< detail::let_< As... > >> let
A lexically scoped expression with local variables.
Definition: meta.hpp:3660
if_c<(sizeof...(Ts) > 0), detail::lambda_< list< Ts... > >> lambda
For creating anonymous Invocables.
Definition: meta.hpp:3594
meta::size_t< sizeof(T)> sizeof_
An alias that computes the size of the type T.
Definition: meta.hpp:824
_t< id< T > > id_t
An alias for type T.
Definition: meta.hpp:577
void void_
An alias for void.
Definition: meta.hpp:597
meta::size_t< alignof(T)> alignof_
An alias that computes the alignment required for any instance of the type T.
Definition: meta.hpp:831
fold< L, pair< list<>, list<> >, detail::partition_< Fn > > partition
Returns a pair of lists, where the elements of L that satisfy the invocable Fn such that invoke<Fn,...
Definition: meta.hpp:3209
_t< detail::sort_< L, Fn > > sort
Return a new meta::list that is sorted according to invocable predicate Fn.
Definition: meta.hpp:3277
_t< detail::transform_< list< Args... > >> transform
Return a new meta::list constructed by transforming all the elements in L with the unary invocable Fn...
Definition: meta.hpp:1855
apply< bind_front< quote< list >, Ts... >, L > push_front
Return a new meta::list by adding the element T to the front of L.
Definition: meta.hpp:2120
fold< ListOfLists, repeat_n< size< front< ListOfLists > >, list<> >, bind_back< quote< transform >, quote< push_back > >> transpose
Given a list of lists of types ListOfLists, transpose the elements from the lists.
Definition: meta.hpp:2892
_t< detail::replace_< L, T, U > > replace
Return a new meta::list where all instances of type T have been replaced with U.
Definition: meta.hpp:2619
drop_c< L, N::type::value > drop
Return a new meta::list by removing the first N elements from L.
Definition: meta.hpp:2037
transpose< ListOfLists > zip
Given a list of lists of types ListOfLists, construct a new list by grouping the elements from the li...
Definition: meta.hpp:2930
reverse_fold< ListOfLists, list< list<> >, quote_trait< detail::cartesian_product_fn > > cartesian_product
Given a list of lists ListOfLists, return a new list of lists that is the Cartesian Product.
Definition: meta.hpp:3720
_t< detail::reverse_fold_< L, State, Fn > > reverse_fold
Return a new meta::list constructed by doing a right fold of the list L using binary invocable Fn and...
Definition: meta.hpp:1661
fold< L, list<>, quote_trait< detail::insert_back_ > > unique
Return a new meta::list where all duplicate elements have been removed.
Definition: meta.hpp:3157
_t< detail::concat_< Ls... > > concat_
Concatenates several lists into a single list.
Definition: meta.hpp:1765
_t< detail::replace_if_< L, C, U > > replace_if
Return a new meta::list where all elements A of the list L for which invoke<C,A>::value is true have ...
Definition: meta.hpp:2669
join< transform< L, detail::filter_< Pred > >> filter
Returns a new meta::list where only those elements of L that satisfy the Callable Pred such that invo...
Definition: meta.hpp:2818
_t< detail::drop_< L, N > > drop_c
Return a new meta::list by removing the first N elements from L.
Definition: meta.hpp:2030
transform< transpose< ListOfLists >, uncurry< Fn > > zip_with
Given a list of lists of types ListOfLists and an invocable Fn, construct a new list by calling Fn wi...
Definition: meta.hpp:2911
fold< L, State, Fn > accumulate
An alias for meta::fold.
Definition: meta.hpp:1597
_t< detail::fold_< L, id< State >, Fn > > fold
Return a new meta::list constructed by doing a left fold of the list L using binary invocable Fn and ...
Definition: meta.hpp:1589
_t< detail::pop_front_< L > > pop_front
Return a new meta::list by removing the first element from the front of L.
Definition: meta.hpp:2154
apply< quote< concat >, ListOfLists > join
Joins a list of lists into a single list.
Definition: meta.hpp:1786
_t< detail::reverse_< L > > reverse
Return a new meta::list by reversing the elements in the list L.
Definition: meta.hpp:2996
apply< bind_back< quote< list >, Ts... >, L > push_back
Return a new meta::list by adding the element T to the back of L.
Definition: meta.hpp:2173
constexpr T * _nullptr_v()
Returns a T nullptr.
Definition: meta.hpp:121
Forward declarations.
Tiny metaprogramming library.
Definition: meta.hpp:116
std::integral_constant< decltype(T::type::value+1), T::type::value+1 > inc
An integral constant wrapper around the result of incrementing the wrapped integer T::type::value.
Definition: meta.hpp:185
detail::protect_< T > protect
For preventing the evaluation of a nested defered computation in a let or lambda expression.
Definition: meta.hpp:3615
detail::vararg_< T > vararg
For defining variadic placeholders.
Definition: meta.hpp:3608
std::integral_constant< decltype(T::type::value - 1), T::type::value - 1 > dec
An integral constant wrapper around the result of decrementing the wrapped integer T::type::value.
Definition: meta.hpp:190
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition: hash.hpp:34
Definition: meta.hpp:1383
An invocable that partially applies the invocable Fn by binding the arguments Us to the back of Fn.
Definition: meta.hpp:979
An invocable that partially applies the invocable Fn by binding the arguments Ts to the front of Fn.
Definition: meta.hpp:969
Compose the Invocables Fns in the parameter pack Ts.
Definition: meta.hpp:881
A wrapper that defers the instantiation of a template C with integral constant parameters Is in a lam...
Definition: meta.hpp:798
A wrapper that defers the instantiation of a template C with type parameters Ts in a lambda or let ex...
Definition: meta.hpp:787
Definition: meta.hpp:2685
Definition: meta.hpp:2754
A trait that unpacks the types in the type list L into the invocable Fn.
Definition: meta.hpp:1005
An invocable that reverses the order of the first two arguments.
Definition: meta.hpp:1068
A trait that always returns its argument T.
Definition: meta.hpp:558
A container for a sequence of compile-time integer constants.
Definition: meta.hpp:434
static constexpr std::size_t size() noexcept
Definition: meta.hpp:437
A list of types.
Definition: meta.hpp:1684
static constexpr std::size_t size() noexcept
Definition: meta.hpp:1687
An empty type.
Definition: meta.hpp:135
Logically OR together all the Boolean parameters.
Definition: meta.hpp:1432
Turn a template C taking literals of type T into a invocable.
Definition: meta.hpp:925
Turn a template C into an invocable.
Definition: meta.hpp:913
For use when defining local variables in meta::let expressions.
Definition: meta.hpp:3622