Horizon
Loading...
Searching...
No Matches
meta.hpp
Go to the documentation of this file.
1
2//
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
115namespace 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>
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>
447 using index_sequence = integer_sequence<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>
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>
969 {
970 template <typename... Us>
971 using invoke = invoke<Fn, Ts..., Us...>;
972 };
973
977 template <META_TYPE_CONSTRAINT(invocable) Fn, typename... Us>
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>
1148 using conditional_t = typename detail::_cond<If>::template invoke<Then, Else>;
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>
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>
1467 using and_ = defer<and_, Bs...>;
1468
1471 template <typename... Bs>
1472 using or_ = defer<or_, Bs...>;
1473
1476 template <typename B>
1478
1481 template <typename... Bs>
1482 using strict_and = defer<strict_and, Bs...>;
1483
1486 template <typename... Bs>
1487 using strict_or = defer<strict_or, 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
1676 using npos = meta::size_t<std::size_t(-1)>;
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>
1696 using size = meta::size_t<L::size()>;
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>
2198
2199 template <typename... Ts>
2200 using min = min_<Ts...>;
2201
2204 template <META_TYPE_CONSTRAINT(integral)... Ts>
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>
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>
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>
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<
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)
3790META_BEGIN_NAMESPACE_STD
3791META_BEGIN_NAMESPACE_VERSION
3792template <class>
3793class META_TEMPLATE_VIS allocator;
3794template <class, class>
3795struct META_TEMPLATE_VIS pair;
3796template <class>
3797struct META_TEMPLATE_VIS hash;
3798template <class>
3799struct META_TEMPLATE_VIS less;
3800template <class>
3801struct META_TEMPLATE_VIS equal_to;
3802template <class>
3803struct META_TEMPLATE_VIS char_traits;
3804#if defined(_GLIBCXX_USE_CXX11_ABI) && _GLIBCXX_USE_CXX11_ABI
3805inline namespace __cxx11 {
3806#endif
3807template <class, class, class>
3808class META_TEMPLATE_VIS basic_string;
3809#if defined(_GLIBCXX_USE_CXX11_ABI) && _GLIBCXX_USE_CXX11_ABI
3810}
3811#endif
3812META_END_NAMESPACE_VERSION
3813META_BEGIN_NAMESPACE_CONTAINER
3814#if defined(__GLIBCXX__)
3815inline namespace __cxx11 {
3816#endif
3817template <class, class>
3818class META_TEMPLATE_VIS list;
3819#if defined(__GLIBCXX__)
3820}
3821#endif
3822template <class, class>
3823class META_TEMPLATE_VIS forward_list;
3824template <class, class>
3825class META_TEMPLATE_VIS vector;
3826template <class, class>
3827class META_TEMPLATE_VIS deque;
3828template <class, class, class, class>
3829class META_TEMPLATE_VIS map;
3830template <class, class, class, class>
3831class META_TEMPLATE_VIS multimap;
3832template <class, class, class>
3833class META_TEMPLATE_VIS set;
3834template <class, class, class>
3835class META_TEMPLATE_VIS multiset;
3836template <class, class, class, class, class>
3837class META_TEMPLATE_VIS unordered_map;
3838template <class, class, class, class, class>
3839class META_TEMPLATE_VIS unordered_multimap;
3840template <class, class, class, class>
3841class META_TEMPLATE_VIS unordered_set;
3842template <class, class, class, class>
3843class META_TEMPLATE_VIS unordered_multiset;
3844template <class, class>
3845class META_TEMPLATE_VIS queue;
3846template <class, class, class>
3847class META_TEMPLATE_VIS priority_queue;
3848template <class, class>
3849class META_TEMPLATE_VIS stack;
3850META_END_NAMESPACE_CONTAINER
3851META_END_NAMESPACE_STD
3852
3853namespace 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
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
bind_front< quote< apply >, Fn > uncurry
An invocable that takes a type list, unpacks the types, and then calls the invocable Fn with the type...
Definition meta.hpp:1049
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
_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< bind_back, Fn, Ts... > bind_back
Definition meta.hpp:994
defer< invoke, Fn, Args... > invoke
Definition meta.hpp:549
defer< strict_or, Bs... > strict_or
Definition meta.hpp:1487
defer< strict_and, Bs... > strict_and
Definition meta.hpp:1482
defer< if_, Args... > if_
Definition meta.hpp:1258
defer< or_, Bs... > or_
Definition meta.hpp:1472
defer< and_, Bs... > and_
Definition meta.hpp:1467
defer< min, Ts... > min
Definition meta.hpp:2215
defer< max, Ts... > max
Definition meta.hpp:2220
defer< let, As... > let
Definition meta.hpp:3667
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< 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