Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
tuplet.hpp
Go to the documentation of this file.
1// From http://github.com/codeinred/tuplet.
2// See https://github.com/codeinred/tuplet/blob/main/LICENSE.
3
4#ifndef TUPLET_TUPLET_HPP_IMPLEMENTATION
5#define TUPLET_TUPLET_HPP_IMPLEMENTATION
6
7#include <cstddef>
8#include <type_traits>
9#include <utility>
10
14
15#if TUPLET_NO_INLINE
16#define TUPLET_INLINE
17#else
18
19#if _MSC_VER
20#define TUPLET_INLINE __forceinline
21#elif __GNUC__ || __clang__
22#define TUPLET_INLINE [[gnu::always_inline]]
23#else
24#define TUPLET_INLINE
25#endif
26#endif
27
28#define _TUPLET_COMPARISON_OPERATOR_1(type, member, op) \
29 TUPLET_INLINE constexpr auto operator op(type const& other) const noexcept(noexcept(member op other.member)) \
30 { \
31 return member op other.member; \
32 }
33
34#if _MSC_VER
36#define TUPLET_FWD_M(TupleType, BaseType, tup, value) \
37 static_cast<::tuplet::forward_as_t<TupleType&&, BaseType>>(tup).value
39#define TUPLET_GET_M(BaseType, tup, value) tup.::tuplet::identity_t<BaseType>::value
40#elif __clang__
42#define TUPLET_FWD_M(TupleType, BaseType, tup, value) \
43 static_cast<TupleType&&>(tup).::tuplet::identity_t<BaseType>::value
44#define TUPLET_GET_M(BaseType, tup, value) tup.::tuplet::identity_t<BaseType>::value
45#else
47#define TUPLET_FWD_M(TupleType, BaseType, tup, value) static_cast<TupleType&&>(tup).BaseType::value
48#define TUPLET_GET_M(BaseType, tup, value) tup.BaseType::value
49#endif
50
51#if __cpp_impl_three_way_comparison && __cpp_lib_three_way_comparison && !defined(TUPLET_DEFAULTED_COMPARISON)
52#define TUPLET_DEFAULTED_COMPARISON 1
53#include <compare>
54#else
55#define TUPLET_DEFAULTED_COMPARISON 0
56#endif
57
58#if __cpp_concepts
59#define TUPLET_OTHER_THAN(Self, Other) tuplet::other_than<Self> Other
60#define TUPLET_WEAK_CONCEPT(...) __VA_ARGS__
61#define TUPLET_WEAK_REQUIRES(...) requires __VA_ARGS__
62#define _TUPLET_TYPES_EQ_WITH(T, U) \
63 bool \
64 requires(::tuplet::equality_comparable_with<T, U> && ...)
65#define _TUPLET_TYPES_CMP_WITH(T, U) \
66 bool \
67 requires(::tuplet::equality_comparable_with<T, U> && ...)
68#else
69#define TUPLET_OTHER_THAN(Self, Other) class Other, class = ::tuplet::sfinae::other_than<Self, Other>
70#define TUPLET_WEAK_CONCEPT(...) class
71#define TUPLET_WEAK_REQUIRES(...)
72#if _MSC_VER < 1930
73#define _TUPLET_TYPES_EQ_WITH(T, U) \
74 ::std::enable_if_t<::tuplet::sfinae::detail::_all_true<::tuplet::sfinae::detail::_has_eq<T, U>...>(), bool>
75#define _TUPLET_TYPES_CMP_WITH(T, U) \
76 ::std::enable_if_t<::tuplet::sfinae::detail::_all_true<::tuplet::sfinae::detail::_has_cmp<T, U>...>(), bool>
77#else
78#define _TUPLET_TYPES_EQ_WITH(T, U) ::std::enable_if_t<((::tuplet::sfinae::detail::_has_eq<T, U>) && ...), bool>
79#define _TUPLET_TYPES_CMP_WITH(T, U) ::std::enable_if_t<((::tuplet::sfinae::detail::_has_cmp<T, U>) && ...), bool>
80#endif
81#endif
82
83#if defined(TUPLET_NO_UNIQUE_ADDRESS) && !TUPLET_NO_UNIQUE_ADDRESS
84#define TUPLET_NO_UNIQUE_ADDRESS
85#else
86#if _MSVC_LANG >= 202002L && (!defined __clang__)
87
88#define TUPLET_HAS_NO_UNIQUE_ADDRESS 1
89#define TUPLET_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
90
91#elif _MSC_VER
92// no_unique_address is not available (C++17)
93#define TUPLET_HAS_NO_UNIQUE_ADDRESS 0
94#define TUPLET_NO_UNIQUE_ADDRESS
95
96#elif __cplusplus > 201703L && (__has_cpp_attribute(no_unique_address))
97
98#define TUPLET_HAS_NO_UNIQUE_ADDRESS 1
99#define TUPLET_NO_UNIQUE_ADDRESS [[no_unique_address]]
100
101#else
102// no_unique_address is not available.
103#define TUPLET_HAS_NO_UNIQUE_ADDRESS 0
104#define TUPLET_NO_UNIQUE_ADDRESS
105#endif
106#endif
107
111
112namespace tuplet {
114template <class... T> struct type_list {};
115
117template <class... Ls, class... Rs> TUPLET_INLINE constexpr auto operator+(type_list<Ls...>, type_list<Rs...>)
118{
119 return type_list<Ls..., Rs...>{};
120}
121} // namespace tuplet
122
126
129{
130 return true;
131}
132
133template <class T, class U> constexpr bool _test_eq(long long)
134{
135 return false;
136}
137
142
143template <class T, class U> constexpr bool _test_less(long long)
144{
145 return false;
146}
147
148template <class T, class U> constexpr bool _has_eq = _test_eq<T, U>(0);
149
150template <class T, class U = T> constexpr bool _has_cmp = _test_eq<T, U>(0) && _test_less<T, U>(0);
151
152template <class Tup, class = typename Tup::base_list> constexpr bool _has_base_list(int)
153{
154 return true;
155}
156template <class Tup> constexpr bool _has_base_list(long long)
157{
158 return false;
159}
160
161template <bool... B> constexpr bool _all_true()
162{
163 return (B && ...);
164};
165
166template <class... T, class... U> constexpr bool _all_has_eq(type_list<T...>, type_list<U...>)
167{
168 bool values[]{ _has_eq<T, U>... };
169 for (bool b : values) {
170 if (!b) {
171 return false;
172 }
173 }
174 return true;
175}
176template <class... T, class... U> constexpr bool _all_has_cmp(type_list<T...>, type_list<U...>)
177{
178 bool values[]{ _has_cmp<T, U>... };
179 for (bool b : values) {
180 if (!b) {
181 return false;
182 }
183 }
184 return true;
185}
186
188{
189 return true;
190}
192{
193 return true;
194}
195
197constexpr bool _test_m_compare(int)
198{
199 return true;
200}
201
202template <class, class> constexpr bool _test_m_compare(long long)
203{
204 return false;
205}
206} // namespace tuplet::sfinae::detail
207
208namespace tuplet::sfinae {
211} // namespace tuplet::sfinae
212
213namespace tuplet::detail {
214template <class Tup, class B> struct _forward_as {
215 using type = B&&;
216};
217
218template <class Tup, class B> struct _forward_as<Tup&, B> {
219 using type = B&;
220};
221
222template <class Tup, class B> struct _forward_as<Tup&&, B> {
223 using type = B&&;
224};
225
226template <class Tup, class B> struct _forward_as<Tup const&, B> {
227 using type = B const&;
228};
229
230template <class Tup, class B> struct _forward_as<Tup const&&, B> {
231 using type = B const&&;
232};
233} // namespace tuplet::detail
234
235namespace tuplet {
236template <class T> struct unwrap_reference {
237 using type = T;
238};
239template <class U> struct unwrap_reference<std::reference_wrapper<U>> {
240 using type = U&;
241};
242
243template <class T> struct unwrap_ref_decay : unwrap_reference<std::decay_t<T>> {};
244
245template <class T> using unwrap_ref_decay_t = typename unwrap_ref_decay<T>::type;
246
247template <class T> using identity_t = T;
248
251template <class Tup, class B> using forward_as_t = typename ::tuplet::detail::_forward_as<Tup, B>::type;
252
253template <class First, class...> using first_t = First;
254
255// Obtains T::type
256template <class T> using type_t = typename T::type;
257
258template <size_t I> using tag = std::integral_constant<size_t, I>;
259
260template <size_t I> constexpr tag<I> tag_v{};
261
262template <size_t N> using tag_range = std::make_index_sequence<N>;
263
264template <class Tup> using base_list_t = typename std::decay_t<Tup>::base_list;
265template <class Tup> using element_list_t = typename std::decay_t<Tup>::element_list;
266
267template <class T> constexpr bool stateless_v = std::is_empty_v<std::decay_t<T>>;
268
269#if __cpp_concepts
270template <class T, class U>
272
273template <class T, class U>
274concept other_than = !std::is_same_v<std::decay_t<T>, std::decay_t<U>>;
275
276template <class Tuple>
277concept base_list_tuple = requires() { typename std::decay_t<Tuple>::base_list; };
278
279template <class T>
281
282template <class T>
283concept indexable = stateless<T> || requires(T t) { t[tag<0>()]; };
284
285template <class U, class T>
286concept assignable_to = requires(U u, T t) { t = u; };
287
288template <class T>
289concept ordered = requires(T const& t) {
290 { t <=> t };
291};
292
293template <class T, class U>
294concept ordered_with = requires(T const& t, U const& u) {
295 { t <=> u };
296};
297template <class T>
298concept equality_comparable = requires(T const& t) {
299 { t == t } -> same_as<bool>;
300};
301
302template <class T, class U>
303concept equality_comparable_with = requires(T const& t, U const& u) {
304 { t == u } -> same_as<bool>;
305};
306
307template <class T>
308concept partial_comparable = equality_comparable<T> && requires(T const& t) {
309 { t < t } -> same_as<bool>;
310};
311template <class T, class U>
312concept partial_comparable_with = equality_comparable_with<T, U> && requires(T const& t, U const& u) {
313 { t < u } -> same_as<bool>;
314 { t > u } -> same_as<bool>;
315};
316
317#endif
318
319template <class Tuple>
320constexpr auto base_list_tuple_v =
321#if __cpp_concepts
323#else
324 tuplet::sfinae::detail::_has_base_list<Tuple>(0);
325#endif
326} // namespace tuplet
327
331
332namespace tuplet::detail {
335template <class T, class U> TUPLET_INLINE constexpr bool _partial_cmp(T const& a, U const& b, bool& less)
336{
337 if constexpr (::tuplet::sfinae::detail::_test_m_compare<T, U>(0)) {
338 int cmp = a.compare(b);
339
340 if (cmp < 0) {
341 less = true;
342 }
343 return cmp == 0;
344 } else {
345#if TUPLET_DEFAULTED_COMPARISON
346 if constexpr (ordered_with<T, U>) {
347 auto cmp = a <=> b;
348
349 if (cmp < 0) {
350 less = true;
351 }
352 return cmp == 0;
353 } else {
354 if (a < b) {
355 less = true;
356 return false;
357 } else {
358 return a == b;
359 }
360 }
361#else
362 if (a < b) {
363 less = true;
364 return false;
365 } else {
366 return a == b;
367 }
368#endif
369 }
370}
371
372template <class Tup, class... B1> TUPLET_INLINE constexpr bool _equals(Tup const& t1, Tup const& t2, type_list<B1...>)
373{
374#ifdef _MSC_VER
375 return [&](auto&... v1) -> bool {
376 return [&](auto&... v2) -> bool { return ((v1 == v2) && ...); }(TUPLET_GET_M(B1, t2, value)...);
377 }(TUPLET_GET_M(B1, t1, value)...);
378#else
379 return ((TUPLET_GET_M(B1, t1, value) == TUPLET_GET_M(B1, t2, value)) && ...);
380#endif
381}
382
383template <class Tup, class... B1> TUPLET_INLINE constexpr bool _less(Tup const& t1, Tup const& t2, type_list<B1...>)
384{
385 bool is_less = false;
386#ifdef _MSC_VER
387 [&](auto&... v1) -> bool {
388 return
389 [&](auto&... v2) -> bool { return (_partial_cmp(v1, v2, is_less) && ...); }(TUPLET_GET_M(B1, t2, value)...);
390 }(TUPLET_GET_M(B1, t1, value)...);
391#else
393#endif
394 return is_less;
395}
396
397template <class Tup, class... B1> TUPLET_INLINE constexpr bool _less_eq(Tup const& t1, Tup const& t2, type_list<B1...>)
398{
399 bool is_less = false;
400#ifdef _MSC_VER
401 bool is_eq = [&](auto&... v1) -> bool {
402 return
403 [&](auto&... v2) -> bool { return (_partial_cmp(v1, v2, is_less) && ...); }(TUPLET_GET_M(B1, t2, value)...);
404 }(TUPLET_GET_M(B1, t1, value)...);
405#else
406 bool is_eq = (_partial_cmp(TUPLET_GET_M(B1, t1, value), TUPLET_GET_M(B1, t2, value), is_less) && ... && true);
407#endif
408 return is_less || is_eq;
409}
410
411template <class Tup1, class Tup2, class... B1, class... B2>
413{
414#ifdef _MSC_VER
415 return [&](auto&... v1) -> bool {
416 return [&](auto&... v2) -> bool { return ((v1 == v2) && ...); }(TUPLET_GET_M(B2, t2, value)...);
417 }(TUPLET_GET_M(B1, t1, value)...);
418#else
419 return ((TUPLET_GET_M(B1, t1, value) == TUPLET_GET_M(B2, t2, value)) && ...);
420#endif
421}
422
423template <class Tup1, class Tup2, class... B1, class... B2>
425{
426 bool is_less = false;
427#ifdef _MSC_VER
428 [&](auto&... v1) -> bool {
429 return
430 [&](auto&... v2) -> bool { return (_partial_cmp(v1, v2, is_less) && ...); }(TUPLET_GET_M(B2, t2, value)...);
431 }(TUPLET_GET_M(B1, t1, value)...);
432#else
433 (_partial_cmp(TUPLET_GET_M(B1, t1, value), TUPLET_GET_M(B2, t2, value), is_less) && ... && true);
434#endif
435 return is_less;
436}
437
438template <class Tup1, class Tup2, class... B1, class... B2>
440{
441 bool is_less = false;
442#ifdef _MSC_VER
443 bool is_eq = [&](auto&... v1) -> bool {
444 return
445 [&](auto&... v2) -> bool { return (_partial_cmp(v1, v2, is_less) && ...); }(TUPLET_GET_M(B2, t2, value)...);
446 }(TUPLET_GET_M(B1, t1, value)...);
447#else
448 bool is_eq = (_partial_cmp(TUPLET_GET_M(B1, t1, value), TUPLET_GET_M(B2, t2, value), is_less) && ... && true);
449#endif
450 return is_less || is_eq;
451}
452} // namespace tuplet::detail
453
457
458namespace tuplet {
459template <class... Bases> struct type_map : Bases... {
460 using base_list = type_list<Bases...>;
461 using Bases::operator[]...;
462 using Bases::decl_elem...;
463
464#if TUPLET_DEFAULTED_COMPARISON
465 TUPLET_INLINE auto operator<=>(type_map const&) const = default;
466 TUPLET_INLINE bool operator==(type_map const&) const = default;
467#else
468 TUPLET_INLINE constexpr auto operator==(type_map const& other) const
469 {
470 return detail::_equals(*this, other, base_list{});
471 }
472 TUPLET_INLINE constexpr auto operator!=(type_map const& other) const { return !(*this == other); }
473 TUPLET_INLINE constexpr auto operator<(type_map const& other) const
474 {
475 return detail::_less(*this, other, base_list{});
476 }
477 TUPLET_INLINE constexpr auto operator<=(type_map const& other) const
478 {
479 return detail::_less_eq(*this, other, base_list{});
480 }
481 TUPLET_INLINE constexpr auto operator>(type_map const& other) const
482 {
483 return detail::_less(other, *this, base_list{});
484 }
485 TUPLET_INLINE constexpr auto operator>=(type_map const& other) const
486 {
487 return detail::_less_eq(other, *this, base_list{});
488 }
489#endif
490};
491} // namespace tuplet
492
496
497namespace tuplet {
498template <size_t I, class T> struct tuple_elem {
499 // Like declval, but with the element
500 static T decl_elem(tag<I>);
501 using type = T;
502
504
505 TUPLET_INLINE constexpr decltype(auto) operator[](tag<I>) & { return (value); }
506 TUPLET_INLINE constexpr decltype(auto) operator[](tag<I>) const& { return (value); }
507 TUPLET_INLINE constexpr decltype(auto) operator[](tag<I>) && { return (static_cast<tuple_elem&&>(*this).value); }
508#if TUPLET_DEFAULTED_COMPARISON
509 TUPLET_INLINE auto operator<=>(tuple_elem const&) const = default;
510 TUPLET_INLINE bool operator==(tuple_elem const&) const = default;
511 // Implements comparison for tuples containing reference types
512 TUPLET_INLINE constexpr auto operator<=>(tuple_elem const& other) const noexcept(noexcept(value <=> other.value))
514 {
515 return value <=> other.value;
516 }
517 TUPLET_INLINE constexpr bool operator==(tuple_elem const& other) const noexcept(noexcept(value == other.value))
519 {
520 return value == other.value;
521 }
522#else
523 _TUPLET_COMPARISON_OPERATOR_1(tuple_elem, value, ==)
524 _TUPLET_COMPARISON_OPERATOR_1(tuple_elem, value, !=)
526 _TUPLET_COMPARISON_OPERATOR_1(tuple_elem, value, <=)
528 _TUPLET_COMPARISON_OPERATOR_1(tuple_elem, value, >=)
529#endif
530};
531} // namespace tuplet
532
536
537namespace tuplet::detail {
538template <class IndexSequence, class... T> struct _get_tuple_base;
539
540template <size_t... I, class... T> struct _get_tuple_base<std::index_sequence<I...>, T...> {
542};
543} // namespace tuplet::detail
544
545namespace tuplet {
548template <class... T> using tuple_base_t = typename detail::_get_tuple_base<tag_range<sizeof...(T)>, T...>::type;
549} // namespace tuplet
550
554
555namespace tuplet {
556template <class... T> struct tuple;
557}
558
559namespace tuplet::detail {
560template <class Tup, class F, class... B> TUPLET_INLINE constexpr void _for_each(Tup&& tup, F&& func, type_list<B...>)
561{
562 (void(func(TUPLET_FWD_M(Tup, B, tup, value))), ...);
563}
564
565template <class Tup, class F, class... B> TUPLET_INLINE constexpr bool _any(Tup&& tup, F&& func, type_list<B...>)
566{
567#ifdef _MSC_VER
568 return [&](auto&&... v1) -> bool {
569 return (bool(func(static_cast<decltype(v1)&&>(v1))) || ...);
570 }(TUPLET_FWD_M(Tup, B, tup, value)...);
571#else
572 return (bool(func(TUPLET_FWD_M(Tup, B, tup, value))) || ...);
573#endif
574}
575
576template <class Tup, class F, class... B> TUPLET_INLINE constexpr bool _all(Tup&& tup, F&& func, type_list<B...>)
577{
578#ifdef _MSC_VER
579 return [&](auto&&... v1) -> bool {
580 return (bool(func(static_cast<decltype(v1)&&>(v1))) && ...);
581 }(TUPLET_FWD_M(Tup, B, tup, value)...);
582#else
583 return (bool(func(TUPLET_FWD_M(Tup, B, tup, value))) && ...);
584#endif
585}
586
587template <class Tup, class F, class... B>
589 -> tuple<decltype(func(TUPLET_FWD_M(Tup, B, tup, value)))...>
590{
591 return { func(TUPLET_FWD_M(Tup, B, tup, value))... };
592}
593
594template <class Tup, class F, class... B> TUPLET_INLINE constexpr decltype(auto) _apply(Tup&& t, F&& f, type_list<B...>)
595{
596 return static_cast<F&&>(f)(TUPLET_FWD_M(Tup, B, t, value)...);
597}
598
599template <class U, class Tup, class... B> TUPLET_INLINE constexpr U _convert(Tup&& t, type_list<B...>)
600{
601 return U{ TUPLET_FWD_M(Tup, B, t, value)... };
602}
603} // namespace tuplet::detail
604
608
609namespace tuplet {
610template <class... T> struct tuple : tuple_base_t<T...> {
611 constexpr static size_t N = sizeof...(T);
612 constexpr static bool
613#if _MSC_VER
614 nothrow_swappable = ::tuplet::sfinae::detail::_all_true<std::is_nothrow_swappable_v<T>...>();
615#else
617#endif
618 using super = tuple_base_t<T...>;
619 using super::operator[];
620 using base_list = typename super::base_list;
621 using element_list = type_list<T...>;
622 using super::decl_elem;
623
624 template <TUPLET_OTHER_THAN(tuple, U)> // Preserves default assignments
625 TUPLET_INLINE constexpr auto& operator=(U&& tup)
626 {
627 using tuple2 = std::decay_t<U>;
628 if constexpr (base_list_tuple_v<tuple2>) {
629 _assign_tup(static_cast<U&&>(tup), base_list{}, typename tuple2::base_list{});
630 } else {
631 _assign_index_tup(static_cast<U&&>(tup), tag_range<N>());
632 }
633 return *this;
634 }
635
636 template <class... U> TUPLET_WEAK_REQUIRES((assignable_to<U, T> && ...)) constexpr auto& assign(U&&... values)
637 {
638 _assign(base_list{}, static_cast<U&&>(values)...);
639 return *this;
640 }
641
642#if TUPLET_DEFAULTED_COMPARISON
643 TUPLET_INLINE auto operator<=>(tuple const&) const = default;
644 TUPLET_INLINE bool operator==(tuple const&) const = default;
645 TUPLET_INLINE bool operator!=(tuple const&) const = default;
646 TUPLET_INLINE bool operator<(tuple const&) const = default;
647 TUPLET_INLINE bool operator>(tuple const&) const = default;
648 TUPLET_INLINE bool operator<=(tuple const&) const = default;
649 TUPLET_INLINE bool operator>=(tuple const&) const = default;
650#else
651 TUPLET_INLINE constexpr auto operator==(tuple const& other) const
652 {
653 return detail::_equals(*this, other, base_list{});
654 }
655 TUPLET_INLINE constexpr auto operator!=(tuple const& other) const { return !(*this == other); }
656 TUPLET_INLINE constexpr auto operator<(tuple const& other) const
657 {
658 return detail::_less(*this, other, base_list{});
659 }
660 TUPLET_INLINE constexpr auto operator<=(tuple const& other) const
661 {
662 return detail::_less_eq(*this, other, base_list{});
663 }
664 TUPLET_INLINE constexpr auto operator>(tuple const& other) const
665 {
666 return detail::_less(other, *this, base_list{});
667 }
668 TUPLET_INLINE constexpr auto operator>=(tuple const& other) const
669 {
670 return detail::_less_eq(other, *this, base_list{});
671 }
672#endif
673 template <class... U>
674 TUPLET_INLINE constexpr auto operator==(tuple<U...> const& other) const -> _TUPLET_TYPES_EQ_WITH(T, U)
675 {
676 using other_base_list = typename tuple<U...>::base_list;
677 return detail::_equals(*this, other, base_list{}, other_base_list{});
678 }
679 template <class... U>
680 TUPLET_INLINE constexpr auto operator!=(tuple<U...> const& other) const -> _TUPLET_TYPES_EQ_WITH(T, U)
681 {
682 return !(*this == other);
683 }
684 template <class... U>
685 TUPLET_INLINE constexpr auto operator<(tuple<U...> const& other) const -> _TUPLET_TYPES_CMP_WITH(T, U)
686 {
687 using other_base_list = typename tuple<U...>::base_list;
688 return detail::_less(*this, other, base_list{}, other_base_list{});
689 }
690 template <class... U>
691 TUPLET_INLINE constexpr auto operator<=(tuple<U...> const& other) const -> _TUPLET_TYPES_CMP_WITH(T, U)
692 {
693 using other_base_list = typename tuple<U...>::base_list;
694 return detail::_less_eq(*this, other, base_list{}, other_base_list{});
695 }
696 template <class... U>
697 TUPLET_INLINE constexpr auto operator>(tuple<U...> const& other) const -> _TUPLET_TYPES_CMP_WITH(T, U)
698 {
699 using other_base_list = typename tuple<U...>::base_list;
700 return detail::_less(other, *this, other_base_list{}, base_list{});
701 }
702 template <class... U>
703 TUPLET_INLINE constexpr auto operator>=(tuple<U...> const& other) const -> _TUPLET_TYPES_CMP_WITH(T, U)
704 {
705 using other_base_list = typename tuple<U...>::base_list;
706 return detail::_less_eq(other, *this, other_base_list{}, base_list{});
707 }
708
709 TUPLET_INLINE constexpr void swap(tuple& other) noexcept(nothrow_swappable) { _swap(other, base_list{}); }
710
711 // Applies a function to every element of the tuple. The order is the
712 // declaration order, so first the function will be applied to element
713 // 0, then element 1, then element 2, and so on, where element N is
714 // identified by get<N>
715 template <class F> TUPLET_INLINE constexpr void for_each(F&& func) &
716 {
717 detail::_for_each(*this, static_cast<F&&>(func), base_list{});
718 }
719 template <class F> TUPLET_INLINE constexpr void for_each(F&& func) const&
720 {
721 detail::_for_each(*this, static_cast<F&&>(func), base_list{});
722 }
723 template <class F> TUPLET_INLINE constexpr void for_each(F&& func) &&
724 {
725 detail::_for_each(static_cast<tuple&&>(*this), static_cast<F&&>(func), base_list{});
726 }
727
728 // Applies a function to each element successively, until one returns a
729 // truthy value. Returns true if any application returned a truthy
730 // value, and false otherwise
731 template <class F> TUPLET_INLINE constexpr bool any(F&& func) &
732 {
733 return detail::_any(*this, static_cast<F&&>(func), base_list{});
734 }
735 template <class F> TUPLET_INLINE constexpr bool any(F&& func) const&
736 {
737 return detail::_any(*this, static_cast<F&&>(func), base_list{});
738 }
739 template <class F> TUPLET_INLINE constexpr bool any(F&& func) &&
740 {
741 return detail::_any(static_cast<tuple&&>(*this), static_cast<F&&>(func), base_list{});
742 }
743
744 // Applies a function to each element successively, until one returns a
745 // falsy value. Returns true if every application returned a truthy
746 // value, and false otherwise
747 template <class F> TUPLET_INLINE constexpr bool all(F&& func) &
748 {
749 return detail::_all(*this, static_cast<F&&>(func), base_list{});
750 }
751 template <class F> TUPLET_INLINE constexpr bool all(F&& func) const&
752 {
753 return detail::_all(*this, static_cast<F&&>(func), base_list{});
754 }
755 template <class F> TUPLET_INLINE constexpr bool all(F&& func) &&
756 {
757 return detail::_all(static_cast<tuple&&>(*this), static_cast<F&&>(func), base_list{});
758 }
759
760 // Map a function over every element in the tuple, using the values to
761 // construct a new tuple
762 template <class F> TUPLET_INLINE constexpr auto map(F&& func) &
763 {
764 return detail::_map(*this, static_cast<F&&>(func), base_list{});
765 }
766 template <class F> TUPLET_INLINE constexpr auto map(F&& func) const&
767 {
768 return detail::_map(*this, static_cast<F&&>(func), base_list{});
769 }
770 template <class F> TUPLET_INLINE constexpr auto map(F&& func) &&
771 {
772 return detail::_map(static_cast<tuple&&>(*this), static_cast<F&&>(func), base_list{});
773 }
774
775 template <class F> TUPLET_INLINE constexpr decltype(auto) apply(F&& func) &
776 {
777 return detail::_apply(*this, static_cast<F&&>(func), base_list{});
778 }
779 template <class F> TUPLET_INLINE constexpr decltype(auto) apply(F&& func) const&
780 {
781 return detail::_apply(*this, static_cast<F&&>(func), base_list{});
782 }
783 template <class F> TUPLET_INLINE constexpr decltype(auto) apply(F&& func) &&
784 {
785 return detail::_apply(static_cast<tuple&&>(*this), static_cast<F&&>(func), base_list{});
786 }
787
788 template <class... U> constexpr explicit operator tuplet::tuple<U...>() &
789 {
790 static_assert(sizeof...(U) == N, "Can only convert to tuples with the same number of items");
791 return detail::_convert<tuplet::tuple<U...>>(*this, base_list{});
792 }
793 template <class... U> constexpr explicit operator tuplet::tuple<U...>() const&
794 {
795 static_assert(sizeof...(U) == N, "Can only convert to tuples with the same number of items");
796 return detail::_convert<tuplet::tuple<U...>>(*this, base_list{});
797 }
798 template <class... U> constexpr explicit operator tuplet::tuple<U...>() &&
799 {
800 static_assert(sizeof...(U) == N, "Can only convert to tuples with the same number of items");
801 return detail::_convert<tuplet::tuple<U...>>(static_cast<tuple&&>(*this), base_list{});
802 }
803
805 template <class U> TUPLET_INLINE constexpr U as() & { return detail::_convert<U>(*this, base_list{}); }
807 template <class U> TUPLET_INLINE constexpr U as() const& { return detail::_convert<U>(*this, base_list{}); }
809 template <class U> TUPLET_INLINE constexpr U as() &&
810 {
811 return detail::_convert<U>(static_cast<tuple&&>(*this), base_list{});
812 }
813
814 private:
815 template <class... B> TUPLET_INLINE constexpr void _swap(tuple& other, type_list<B...>) noexcept(nothrow_swappable)
816 {
817 using std::swap;
818 (swap(B::value, TUPLET_GET_M(B, other, value)), ...);
819 }
820
821 template <class U, class... B1, class... B2>
823 {
824 // See:
825 // https://developercommunity.visualstudio.com/t/fold-expressions-unreliable-in-171-with-c20/1676476
826
827 (void(B1::value = TUPLET_FWD_M(U, B2, u, value)), ...);
828 }
829 template <class U, size_t... I> TUPLET_INLINE constexpr void _assign_index_tup(U&& u, std::index_sequence<I...>)
830 {
831 using std::get;
832 (void(tuple_elem<I, T>::value = get<I>(static_cast<U&&>(u))), ...);
833 }
834 template <class... U, class... B> TUPLET_INLINE constexpr void _assign(type_list<B...>, U&&... u)
835 {
836 (void(B::value = static_cast<U&&>(u)), ...);
837 }
838};
839} // namespace tuplet
840
844
845namespace tuplet {
846template <> struct tuple<> : tuple_base_t<> {
847 constexpr static size_t N = 0;
848 constexpr static bool nothrow_swappable = true;
852
853 template <TUPLET_OTHER_THAN(tuple, U)> // Preserves default assignments
854 TUPLET_WEAK_REQUIRES(stateless<U>) // Check that U is similarly stateless
855 constexpr auto&
857 {
858 return *this;
859 }
860
861 constexpr void swap(tuple) noexcept {}
862 constexpr auto& assign() noexcept { return *this; }
863#if TUPLET_DEFAULTED_COMPARISON
864 TUPLET_INLINE auto operator<=>(tuple const&) const = default;
865 TUPLET_INLINE bool operator==(tuple const&) const = default;
866#else
867 TUPLET_INLINE constexpr bool operator==(tuple const&) const noexcept { return true; }
868 TUPLET_INLINE constexpr bool operator<=(tuple const&) const noexcept { return true; }
869 TUPLET_INLINE constexpr bool operator>=(tuple const&) const noexcept { return true; }
870 TUPLET_INLINE constexpr bool operator!=(tuple const&) const noexcept { return false; }
871 TUPLET_INLINE constexpr bool operator<(tuple const&) const noexcept { return false; }
872 TUPLET_INLINE constexpr bool operator>(tuple const&) const noexcept { return false; }
873#endif
874 // Applies a function to every element of the tuple. The order is the
875 // declaration order, so first the function will be applied to element
876 // 0, then element 1, then element 2, and so on, where element N is
877 // identified by get<N>
878 //
879 // (Does nothing when invoked on empty tuple)
880 template <class F> constexpr void for_each(F&&) const noexcept {}
881
882 // Applies a function to each element successively, until one returns a
883 // truthy value. Returns true if any application returned a truthy
884 // value, and false otherwise
885 //
886 // (Returns false for empty tuple)
887 template <class F> constexpr bool any(F&&) const noexcept { return false; }
888
889 // Applies a function to each element successively, until one returns a
890 // falsy value. Returns true if every application returned a truthy
891 // value, and false otherwise
892 //
893 // (Returns true for empty tuple)
894 template <class F> constexpr bool all(F&&) const noexcept { return true; }
895
896 // Map a function over every element in the tuple, using the values to
897 // construct a new tuple
898 //
899 // (Returns empty tuple when invoked on empty tuple)
900 template <class F> constexpr auto map(F&&) const noexcept { return tuple{}; }
901
902 template <class F> constexpr decltype(auto) apply(F&& func) const noexcept { return func(); }
903
904 template <class U> constexpr U as() const noexcept { return U{}; }
905};
906template <class... Ts> tuple(Ts...) -> tuple<unwrap_ref_decay_t<Ts>...>;
907} // namespace tuplet
908
912
913namespace tuplet {
914template <class First, class Second> struct pair {
915 constexpr static size_t N = 2;
919
920 TUPLET_INLINE constexpr decltype(auto) operator[](tag<0>) & { return (first); }
921 TUPLET_INLINE constexpr decltype(auto) operator[](tag<0>) const& { return (first); }
922 TUPLET_INLINE constexpr decltype(auto) operator[](tag<0>) && { return (static_cast<pair&&>(*this).first); }
923 TUPLET_INLINE constexpr decltype(auto) operator[](tag<1>) & { return (second); }
924 TUPLET_INLINE constexpr decltype(auto) operator[](tag<1>) const& { return (second); }
925 TUPLET_INLINE constexpr decltype(auto) operator[](tag<1>) && { return (static_cast<pair&&>(*this).second); }
926
928 {
929 using std::swap;
930 swap(first, other.first);
931 swap(second, other.second);
932 }
933
934 template <TUPLET_OTHER_THAN(pair, Type)> // Preserves default assignments
935 TUPLET_INLINE constexpr auto& operator=(Type&& tup)
936 {
937 auto&& [a, b] = static_cast<Type&&>(tup);
938 first = static_cast<decltype(a)&&>(a);
939 second = static_cast<decltype(b)&&>(b);
940 return *this;
941 }
942
943 template <TUPLET_WEAK_CONCEPT(assignable_to<First>) F2, TUPLET_WEAK_CONCEPT(assignable_to<Second>) S2>
944 TUPLET_INLINE constexpr auto& assign(F2&& f, S2&& s)
945 {
946 first = static_cast<F2&&>(f);
947 second = static_cast<S2&&>(s);
948 return *this;
949 }
950
951#if TUPLET_DEFAULTED_COMPARISON
952 auto operator<=>(pair const&) const = default;
953 bool operator==(pair const&) const = default;
954#else
955 TUPLET_INLINE constexpr bool operator==(pair const& other) const
956 {
957 return first == other.first && second == other.second;
958 }
959 TUPLET_INLINE constexpr bool operator!=(pair const& other) const { return !(*this == other); }
960 TUPLET_INLINE constexpr bool operator<(pair const& other) const
961 {
962 bool result = false;
963 detail::_partial_cmp(first, other.first, result) && detail::_partial_cmp(second, other.second, result);
964 return result;
965 }
966 TUPLET_INLINE constexpr bool operator<=(pair const& other) const
967 {
968 bool result = false;
969 bool is_eq =
970 detail::_partial_cmp(first, other.first, result) && detail::_partial_cmp(second, other.second, result);
971 return result || is_eq;
972 }
973 TUPLET_INLINE constexpr bool operator>(pair const& other) const
974 {
975 bool result = false;
976 detail::_partial_cmp(other.first, first, result) && detail::_partial_cmp(other.second, second, result);
977 return result;
978 }
979 TUPLET_INLINE constexpr bool operator>=(pair const& other) const
980 {
981 bool result = false;
982 bool is_eq =
983 detail::_partial_cmp(other.first, first, result) && detail::_partial_cmp(other.second, second, result);
984 return result || is_eq;
985 }
986#endif
987};
988template <class A, class B> pair(A, B) -> pair<unwrap_ref_decay_t<A>, unwrap_ref_decay_t<B>>;
989} // namespace tuplet
990
994
995namespace tuplet {
996// Converts from one tuple type to any other tuple or U
997template <class Tuple> struct convert {
998 using base_list = typename std::decay_t<Tuple>::base_list;
1000 template <class U> constexpr operator U() &&
1001 {
1002 return detail::_convert<U>(static_cast<Tuple&&>(tuple), base_list{});
1003 }
1004};
1005template <class Tuple> convert(Tuple&) -> convert<Tuple&>;
1006template <class Tuple> convert(Tuple const&) -> convert<Tuple const&>;
1007template <class Tuple> convert(Tuple&&) -> convert<Tuple>;
1008} // namespace tuplet
1009
1013
1014// tuplet::get implementation
1015// tuplet::tie implementation
1016// tuplet::apply implementation
1017// tuplet::swap
1018// tuplet::make_tuple
1019// tuplet::forward_as_tuple
1020namespace tuplet {
1021template <size_t I, TUPLET_WEAK_CONCEPT(indexable) Tup> TUPLET_INLINE constexpr decltype(auto) get(Tup&& tup)
1022{
1023 return static_cast<Tup&&>(tup)[tag<I>()];
1024}
1025
1026template <class... T> TUPLET_INLINE constexpr tuple<T&...> tie(T&... t)
1027{
1028 return { t... };
1029}
1030
1031template <class F, TUPLET_WEAK_CONCEPT(base_list_tuple) Tup>
1032TUPLET_INLINE constexpr decltype(auto) apply(F&& func, Tup&& tup)
1033{
1034 return detail::_apply(static_cast<Tup&&>(tup), static_cast<F&&>(func), typename std::decay_t<Tup>::base_list{});
1035}
1036template <class F, class A, class B> TUPLET_INLINE constexpr decltype(auto) apply(F&& func, tuplet::pair<A, B>& pair)
1037{
1038 return static_cast<F&&>(func)(pair.first, pair.second);
1039}
1040template <class F, class A, class B>
1041TUPLET_INLINE constexpr decltype(auto) apply(F&& func, tuplet::pair<A, B> const& pair)
1042{
1043 return static_cast<F&&>(func)(pair.first, pair.second);
1044}
1045template <class F, class A, class B> TUPLET_INLINE constexpr decltype(auto) apply(F&& func, tuplet::pair<A, B>&& pair)
1046{
1047 using P = tuplet::pair<A, B>&&;
1048 return static_cast<F&&>(func)(static_cast<P>(pair).first, static_cast<P>(pair).second);
1049}
1050
1051template <class... T> TUPLET_INLINE void swap(tuple<T...>& a, tuple<T...>& b) noexcept(tuple<T...>::nothrow_swappable)
1052{
1053 a.swap(b);
1054}
1055
1056template <class A, class B>
1058{
1059 a.swap(b);
1060}
1061
1062template <typename... Ts> TUPLET_INLINE constexpr auto make_tuple(Ts&&... args)
1063{
1064 return tuple<unwrap_ref_decay_t<Ts>...>{ static_cast<Ts&&>(args)... };
1065}
1066
1067template <typename... T> TUPLET_INLINE constexpr auto forward_as_tuple(T&&... a) noexcept
1068{
1069 return tuple<T&&...>{ static_cast<T&&>(a)... };
1070}
1071} // namespace tuplet
1072
1076
1077namespace tuplet::detail {
1078template <class T, class... Q> TUPLET_INLINE constexpr auto _repeat_type(type_list<Q...>)
1079{
1080 return type_list<first_t<T, Q>...>{};
1081}
1082template <class... Outer> TUPLET_INLINE constexpr auto _get_outer_bases(type_list<Outer...>)
1083{
1085}
1086template <class... Outer> TUPLET_INLINE constexpr auto _get_inner_bases(type_list<Outer...>)
1087{
1088 return (base_list_t<type_t<Outer>>{} + ...);
1089}
1090
1091// This takes a forwarding tuple as a parameter. The forwarding tuple only
1092// contains references, so it should just be taken by value.
1093template <class T, class... Outer, class... Inner>
1098} // namespace tuplet::detail
1099
1100namespace tuplet {
1101template <TUPLET_WEAK_CONCEPT(base_list_tuple)... T> constexpr auto tuple_cat(T&&... ts)
1102{
1103 if constexpr (sizeof...(T) == 0) {
1104 return tuple<>();
1105 } else {
1106
1116#if !defined(TUPLET_CAT_BY_FORWARDING_TUPLE)
1117#if defined(__clang__)
1118#define TUPLET_CAT_BY_FORWARDING_TUPLE 0
1119#else
1120#define TUPLET_CAT_BY_FORWARDING_TUPLE 1
1121#endif
1122#endif
1123#if TUPLET_CAT_BY_FORWARDING_TUPLE
1124 using big_tuple = tuple<T&&...>;
1125#else
1126 using big_tuple = tuple<std::decay_t<T>...>;
1127#endif
1129 constexpr auto outer = detail::_get_outer_bases(outer_bases{});
1130 constexpr auto inner = detail::_get_inner_bases(outer_bases{});
1131 return detail::_tuple_cat(big_tuple{ static_cast<T&&>(ts)... }, outer, inner);
1132 }
1133}
1134
1135} // namespace tuplet
1136
1140
1142template <char... D> constexpr size_t _size_t_from_digits()
1143{
1144 static_assert((('0' <= D && D <= '9') && ...), "Must be integral literal");
1145 size_t num = 0;
1146 return ((num = num * 10 + (D - '0')), ..., num);
1147}
1148} // namespace tuplet::literals::detail
1149
1150namespace tuplet::literals {
1151template <char... D> constexpr auto operator""_tag() noexcept -> tag<detail::_size_t_from_digits<D...>()>
1152{
1153 return {};
1154}
1155} // namespace tuplet::literals
1156
1160
1161namespace std {
1162template <class... T> struct tuple_size<tuplet::tuple<T...>> : std::integral_constant<size_t, sizeof...(T)> {};
1163
1164template <size_t I, class... T> struct tuple_element<I, tuplet::tuple<T...>> {
1166};
1167template <class A, class B> struct tuple_size<tuplet::pair<A, B>> : std::integral_constant<size_t, 2> {};
1168
1169template <size_t I, class A, class B> struct tuple_element<I, tuplet::pair<A, B>> {
1170 static_assert(I < 2, "tuplet::pair only has 2 elements");
1172};
1173} // namespace std
1174
1175#endif
FF a
FF b
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
TUPLET_INLINE constexpr bool _any(Tup &&tup, F &&func, type_list< B... >)
Definition tuplet.hpp:565
TUPLET_INLINE constexpr bool _all(Tup &&tup, F &&func, type_list< B... >)
Definition tuplet.hpp:576
TUPLET_INLINE constexpr auto _get_outer_bases(type_list< Outer... >)
Definition tuplet.hpp:1082
TUPLET_INLINE constexpr void _for_each(Tup &&tup, F &&func, type_list< B... >)
Definition tuplet.hpp:560
TUPLET_INLINE constexpr bool _equals(Tup const &t1, Tup const &t2, type_list< B1... >)
Definition tuplet.hpp:372
TUPLET_INLINE constexpr auto _get_inner_bases(type_list< Outer... >)
Definition tuplet.hpp:1086
TUPLET_INLINE constexpr bool _less(Tup const &t1, Tup const &t2, type_list< B1... >)
Definition tuplet.hpp:383
TUPLET_INLINE constexpr decltype(auto) _apply(Tup &&t, F &&f, type_list< B... >)
Definition tuplet.hpp:594
TUPLET_INLINE constexpr bool _partial_cmp(T const &a, U const &b, bool &less)
Definition tuplet.hpp:335
TUPLET_INLINE constexpr bool _less_eq(Tup const &t1, Tup const &t2, type_list< B1... >)
Definition tuplet.hpp:397
TUPLET_INLINE constexpr auto _map(Tup &&tup, F &&func, type_list< B... >) -> tuple< decltype(func(TUPLET_FWD_M(Tup, B, tup, value)))... >
Definition tuplet.hpp:588
TUPLET_INLINE constexpr auto _tuple_cat(T tup, type_list< Outer... >, type_list< Inner... >) -> tuple< type_t< Inner >... >
Definition tuplet.hpp:1094
TUPLET_INLINE constexpr auto _repeat_type(type_list< Q... >)
Definition tuplet.hpp:1078
TUPLET_INLINE constexpr U _convert(Tup &&t, type_list< B... >)
Definition tuplet.hpp:599
constexpr size_t _size_t_from_digits()
Definition tuplet.hpp:1142
constexpr bool _has_cmp
Definition tuplet.hpp:150
constexpr bool _test_m_compare(int)
Definition tuplet.hpp:197
constexpr bool _has_eq
Definition tuplet.hpp:148
constexpr bool _test_eq(int)
Definition tuplet.hpp:128
constexpr bool _all_has_eq(type_list< T... >, type_list< U... >)
Definition tuplet.hpp:166
constexpr bool _test_less(int)
Definition tuplet.hpp:138
constexpr bool _all_has_cmp(type_list< T... >, type_list< U... >)
Definition tuplet.hpp:176
constexpr bool _has_base_list(int)
Definition tuplet.hpp:152
constexpr bool _all_true()
Definition tuplet.hpp:161
std::enable_if_t<!std::is_same_v< std::decay_t< A >, std::decay_t< B > > > other_than
Implement assignment but preserve default assignment.
Definition tuplet.hpp:210
TUPLET_INLINE void swap(tuple< T... > &a, tuple< T... > &b) noexcept(tuple< T... >::nothrow_swappable)
Definition tuplet.hpp:1051
constexpr bool stateless_v
Definition tuplet.hpp:267
TUPLET_INLINE constexpr tuple< T &... > tie(T &... t)
Definition tuplet.hpp:1026
constexpr auto base_list_tuple_v
Definition tuplet.hpp:320
std::integral_constant< size_t, I > tag
Definition tuplet.hpp:258
typename unwrap_ref_decay< T >::type unwrap_ref_decay_t
Definition tuplet.hpp:245
TUPLET_INLINE constexpr auto forward_as_tuple(T &&... a) noexcept
Definition tuplet.hpp:1067
TUPLET_INLINE constexpr auto make_tuple(Ts &&... args)
Definition tuplet.hpp:1062
std::make_index_sequence< N > tag_range
Definition tuplet.hpp:262
constexpr tag< I > tag_v
Definition tuplet.hpp:260
T identity_t
Definition tuplet.hpp:247
constexpr auto tuple_cat(T &&... ts)
Definition tuplet.hpp:1101
TUPLET_INLINE constexpr auto operator+(type_list< Ls... >, type_list< Rs... >)
Convinience + operator for catenating type lists.
Definition tuplet.hpp:117
typename std::decay_t< Tup >::element_list element_list_t
Definition tuplet.hpp:265
typename ::tuplet::detail::_forward_as< Tup, B >::type forward_as_t
Definition tuplet.hpp:251
TUPLET_INLINE constexpr decltype(auto) get(Tup &&tup)
Definition tuplet.hpp:1021
typename std::decay_t< Tup >::base_list base_list_t
Definition tuplet.hpp:264
typename detail::_get_tuple_base< tag_range< sizeof...(T)>, T... >::type tuple_base_t
Definition tuplet.hpp:548
TUPLET_INLINE constexpr decltype(auto) apply(F &&func, Tup &&tup)
Definition tuplet.hpp:1032
typename T::type type_t
Definition tuplet.hpp:256
First first_t
Definition tuplet.hpp:253
std::conditional_t< I==0, A, B > type
Definition tuplet.hpp:1171
decltype(tuplet::tuple< T... >::decl_elem(tuplet::tag< I >())) type
Definition tuplet.hpp:1165
typename std::decay_t< Tuple >::base_list base_list
Definition tuplet.hpp:998
TUPLET_INLINE constexpr auto & operator=(Type &&tup)
Definition tuplet.hpp:935
static constexpr bool nothrow_swappable
Definition tuplet.hpp:916
TUPLET_INLINE constexpr auto & assign(F2 &&f, S2 &&s)
Definition tuplet.hpp:944
TUPLET_INLINE constexpr bool operator!=(pair const &other) const
Definition tuplet.hpp:959
TUPLET_INLINE constexpr bool operator<(pair const &other) const
Definition tuplet.hpp:960
TUPLET_INLINE constexpr bool operator<=(pair const &other) const
Definition tuplet.hpp:966
static constexpr size_t N
Definition tuplet.hpp:915
TUPLET_INLINE void swap(pair &other) noexcept(nothrow_swappable)
Definition tuplet.hpp:927
TUPLET_INLINE constexpr bool operator>(pair const &other) const
Definition tuplet.hpp:973
TUPLET_NO_UNIQUE_ADDRESS First first
Definition tuplet.hpp:917
TUPLET_INLINE constexpr bool operator==(pair const &other) const
Definition tuplet.hpp:955
TUPLET_INLINE constexpr bool operator>=(pair const &other) const
Definition tuplet.hpp:979
TUPLET_NO_UNIQUE_ADDRESS Second second
Definition tuplet.hpp:918
constexpr auto & assign() noexcept
Definition tuplet.hpp:862
TUPLET_INLINE constexpr bool operator>(tuple const &) const noexcept
Definition tuplet.hpp:872
constexpr auto map(F &&) const noexcept
Definition tuplet.hpp:900
constexpr auto & operator=(U &&) noexcept
Definition tuplet.hpp:856
constexpr bool all(F &&) const noexcept
Definition tuplet.hpp:894
constexpr U as() const noexcept
Definition tuplet.hpp:904
TUPLET_INLINE constexpr bool operator<(tuple const &) const noexcept
Definition tuplet.hpp:871
tuple_base_t<> super
Definition tuplet.hpp:849
constexpr bool any(F &&) const noexcept
Definition tuplet.hpp:887
constexpr decltype(auto) apply(F &&func) const noexcept
Definition tuplet.hpp:902
constexpr void swap(tuple) noexcept
Definition tuplet.hpp:861
TUPLET_INLINE constexpr bool operator>=(tuple const &) const noexcept
Definition tuplet.hpp:869
TUPLET_INLINE constexpr bool operator<=(tuple const &) const noexcept
Definition tuplet.hpp:868
TUPLET_INLINE constexpr bool operator==(tuple const &) const noexcept
Definition tuplet.hpp:867
constexpr void for_each(F &&) const noexcept
Definition tuplet.hpp:880
TUPLET_INLINE constexpr bool operator!=(tuple const &) const noexcept
Definition tuplet.hpp:870
static T decl_elem(tag< I >)
TUPLET_NO_UNIQUE_ADDRESS T value
Definition tuplet.hpp:503
TUPLET_INLINE constexpr auto operator>(tuple< U... > const &other) const -> _TUPLET_TYPES_CMP_WITH(T, U)
Definition tuplet.hpp:697
TUPLET_WEAK_REQUIRES((assignable_to< U, T > &&...)) const expr auto &assign(U &&... values)
Definition tuplet.hpp:636
TUPLET_INLINE constexpr U as() &
Instantiate the given type using list initialization.
Definition tuplet.hpp:805
TUPLET_INLINE constexpr bool all(F &&func) &
Definition tuplet.hpp:747
TUPLET_INLINE constexpr auto operator<(tuple< U... > const &other) const -> _TUPLET_TYPES_CMP_WITH(T, U)
Definition tuplet.hpp:685
TUPLET_INLINE constexpr decltype(auto) apply(F &&func) &
Definition tuplet.hpp:775
TUPLET_INLINE constexpr void swap(tuple &other) noexcept(nothrow_swappable)
Definition tuplet.hpp:709
TUPLET_INLINE constexpr bool all(F &&func) const &
Definition tuplet.hpp:751
TUPLET_INLINE constexpr void _assign_index_tup(U &&u, std::index_sequence< I... >)
Definition tuplet.hpp:829
TUPLET_INLINE constexpr void for_each(F &&func) const &
Definition tuplet.hpp:719
TUPLET_INLINE constexpr decltype(auto) apply(F &&func) const &
Definition tuplet.hpp:779
TUPLET_INLINE constexpr auto operator>(tuple const &other) const
Definition tuplet.hpp:664
TUPLET_INLINE constexpr decltype(auto) apply(F &&func) &&
Definition tuplet.hpp:783
TUPLET_INLINE constexpr auto operator>=(tuple< U... > const &other) const -> _TUPLET_TYPES_CMP_WITH(T, U)
Definition tuplet.hpp:703
TUPLET_INLINE constexpr void for_each(F &&func) &
Definition tuplet.hpp:715
static constexpr bool nothrow_swappable
Definition tuplet.hpp:616
tuple_base_t< T... > super
Definition tuplet.hpp:618
TUPLET_INLINE constexpr bool any(F &&func) const &
Definition tuplet.hpp:735
TUPLET_INLINE constexpr auto operator<(tuple const &other) const
Definition tuplet.hpp:656
TUPLET_INLINE constexpr void _assign_tup(U &&u, type_list< B1... >, type_list< B2... >)
Definition tuplet.hpp:822
TUPLET_INLINE constexpr U as() const &
Instantiate the given type using list initialization.
Definition tuplet.hpp:807
typename super::base_list base_list
Definition tuplet.hpp:620
TUPLET_INLINE constexpr void for_each(F &&func) &&
Definition tuplet.hpp:723
TUPLET_INLINE constexpr auto operator>=(tuple const &other) const
Definition tuplet.hpp:668
TUPLET_INLINE constexpr U as() &&
Instantiate the given type using list initialization.
Definition tuplet.hpp:809
TUPLET_INLINE constexpr auto map(F &&func) &&
Definition tuplet.hpp:770
TUPLET_INLINE constexpr auto operator!=(tuple< U... > const &other) const -> _TUPLET_TYPES_EQ_WITH(T, U)
Definition tuplet.hpp:680
TUPLET_INLINE constexpr auto operator<=(tuple const &other) const
Definition tuplet.hpp:660
TUPLET_INLINE constexpr bool any(F &&func) &&
Definition tuplet.hpp:739
TUPLET_INLINE constexpr auto & operator=(U &&tup)
Definition tuplet.hpp:625
TUPLET_INLINE constexpr auto operator==(tuple const &other) const
Definition tuplet.hpp:651
TUPLET_INLINE constexpr auto operator==(tuple< U... > const &other) const -> _TUPLET_TYPES_EQ_WITH(T, U)
Definition tuplet.hpp:674
static constexpr size_t N
Definition tuplet.hpp:611
TUPLET_INLINE constexpr void _assign(type_list< B... >, U &&... u)
Definition tuplet.hpp:834
TUPLET_INLINE constexpr auto operator<=(tuple< U... > const &other) const -> _TUPLET_TYPES_CMP_WITH(T, U)
Definition tuplet.hpp:691
TUPLET_INLINE constexpr bool any(F &&func) &
Definition tuplet.hpp:731
TUPLET_INLINE constexpr auto operator!=(tuple const &other) const
Definition tuplet.hpp:655
TUPLET_INLINE constexpr auto map(F &&func) &
Definition tuplet.hpp:762
TUPLET_INLINE constexpr void _swap(tuple &other, type_list< B... >) noexcept(nothrow_swappable)
Definition tuplet.hpp:815
TUPLET_INLINE constexpr bool all(F &&func) &&
Definition tuplet.hpp:755
TUPLET_INLINE constexpr auto map(F &&func) const &
Definition tuplet.hpp:766
Represents a list of types.
Definition tuplet.hpp:114
TUPLET_INLINE constexpr auto operator>=(type_map const &other) const
Definition tuplet.hpp:485
TUPLET_INLINE constexpr auto operator<(type_map const &other) const
Definition tuplet.hpp:473
TUPLET_INLINE constexpr auto operator<=(type_map const &other) const
Definition tuplet.hpp:477
TUPLET_INLINE constexpr auto operator==(type_map const &other) const
Definition tuplet.hpp:468
TUPLET_INLINE constexpr auto operator!=(type_map const &other) const
Definition tuplet.hpp:472
TUPLET_INLINE constexpr auto operator>(type_map const &other) const
Definition tuplet.hpp:481
#define _TUPLET_TYPES_EQ_WITH(T, U)
Definition tuplet.hpp:73
#define TUPLET_FWD_M(TupleType, BaseType, tup, value)
Looks up a member in a tuple via the base class, and forwards it.
Definition tuplet.hpp:47
#define TUPLET_WEAK_CONCEPT(...)
Definition tuplet.hpp:70
#define TUPLET_NO_UNIQUE_ADDRESS
Definition tuplet.hpp:104
#define _TUPLET_COMPARISON_OPERATOR_1(type, member, op)
Definition tuplet.hpp:28
#define TUPLET_GET_M(BaseType, tup, value)
Definition tuplet.hpp:48
#define TUPLET_WEAK_REQUIRES(...)
Definition tuplet.hpp:71
#define _TUPLET_TYPES_CMP_WITH(T, U)
Definition tuplet.hpp:75
#define TUPLET_INLINE
Definition tuplet.hpp:24