3 // Copyright (C) 2007-2024 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file include/tuple
26 * This is a Standard C++ Library header.
29 #ifndef _GLIBCXX_TUPLE
30 #define _GLIBCXX_TUPLE 1
32 #pragma GCC system_header
34 #if __cplusplus < 201103L
35 # include <bits/c++0x_warning.h>
38 #include <bits/stl_pair.h> // for std::pair
39 #include <bits/uses_allocator.h> // for std::allocator_arg_t
40 #include <bits/utility.h> // for std::tuple_size etc.
41 #include <bits/invoke.h> // for std::__invoke
42 #if __cplusplus > 201703L
44 # include <bits/ranges_util.h> // for std::ranges::subrange
47 #define __glibcxx_want_constexpr_tuple
48 #define __glibcxx_want_tuple_element_t
49 #define __glibcxx_want_tuples_by_type
50 #define __glibcxx_want_apply
51 #define __glibcxx_want_make_from_tuple
52 #define __glibcxx_want_ranges_zip
53 #include <bits/version.h>
55 namespace std _GLIBCXX_VISIBILITY(default)
57 _GLIBCXX_BEGIN_NAMESPACE_VERSION
60 * @addtogroup utilities
64 template<typename... _Elements>
67 template<typename _Tp>
68 struct __is_empty_non_tuple : is_empty<_Tp> { };
70 // Using EBO for elements that are tuples causes ambiguous base errors.
71 template<typename _El0, typename... _El>
72 struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { };
74 // Use the Empty Base-class Optimization for empty, non-final types.
75 template<typename _Tp>
76 using __empty_not_final
77 = __conditional_t<__is_final(_Tp), false_type,
78 __is_empty_non_tuple<_Tp>>;
80 template<size_t _Idx, typename _Head,
81 bool = __empty_not_final<_Head>::value>
84 #if __has_cpp_attribute(__no_unique_address__)
85 template<size_t _Idx, typename _Head>
86 struct _Head_base<_Idx, _Head, true>
88 constexpr _Head_base()
91 constexpr _Head_base(const _Head& __h)
92 : _M_head_impl(__h) { }
94 constexpr _Head_base(const _Head_base&) = default;
95 constexpr _Head_base(_Head_base&&) = default;
97 template<typename _UHead>
98 constexpr _Head_base(_UHead&& __h)
99 : _M_head_impl(std::forward<_UHead>(__h)) { }
102 _Head_base(allocator_arg_t, __uses_alloc0)
105 template<typename _Alloc>
107 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
108 : _M_head_impl(allocator_arg, *__a._M_a) { }
110 template<typename _Alloc>
112 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
113 : _M_head_impl(*__a._M_a) { }
115 template<typename _UHead>
117 _Head_base(__uses_alloc0, _UHead&& __uhead)
118 : _M_head_impl(std::forward<_UHead>(__uhead)) { }
120 template<typename _Alloc, typename _UHead>
122 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
123 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
126 template<typename _Alloc, typename _UHead>
128 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
129 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
131 static constexpr _Head&
132 _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
134 static constexpr const _Head&
135 _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
137 [[__no_unique_address__]] _Head _M_head_impl;
140 template<size_t _Idx, typename _Head>
141 struct _Head_base<_Idx, _Head, true>
144 constexpr _Head_base()
147 constexpr _Head_base(const _Head& __h)
150 constexpr _Head_base(const _Head_base&) = default;
151 constexpr _Head_base(_Head_base&&) = default;
153 template<typename _UHead>
154 constexpr _Head_base(_UHead&& __h)
155 : _Head(std::forward<_UHead>(__h)) { }
158 _Head_base(allocator_arg_t, __uses_alloc0)
161 template<typename _Alloc>
163 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
164 : _Head(allocator_arg, *__a._M_a) { }
166 template<typename _Alloc>
168 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
169 : _Head(*__a._M_a) { }
171 template<typename _UHead>
173 _Head_base(__uses_alloc0, _UHead&& __uhead)
174 : _Head(std::forward<_UHead>(__uhead)) { }
176 template<typename _Alloc, typename _UHead>
178 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
179 : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
181 template<typename _Alloc, typename _UHead>
183 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
184 : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
186 static constexpr _Head&
187 _M_head(_Head_base& __b) noexcept { return __b; }
189 static constexpr const _Head&
190 _M_head(const _Head_base& __b) noexcept { return __b; }
194 template<size_t _Idx, typename _Head>
195 struct _Head_base<_Idx, _Head, false>
197 constexpr _Head_base()
200 constexpr _Head_base(const _Head& __h)
201 : _M_head_impl(__h) { }
203 constexpr _Head_base(const _Head_base&) = default;
204 constexpr _Head_base(_Head_base&&) = default;
206 template<typename _UHead>
207 constexpr _Head_base(_UHead&& __h)
208 : _M_head_impl(std::forward<_UHead>(__h)) { }
211 _Head_base(allocator_arg_t, __uses_alloc0)
214 template<typename _Alloc>
216 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
217 : _M_head_impl(allocator_arg, *__a._M_a) { }
219 template<typename _Alloc>
221 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
222 : _M_head_impl(*__a._M_a) { }
224 template<typename _UHead>
226 _Head_base(__uses_alloc0, _UHead&& __uhead)
227 : _M_head_impl(std::forward<_UHead>(__uhead)) { }
229 template<typename _Alloc, typename _UHead>
231 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
232 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
235 template<typename _Alloc, typename _UHead>
237 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
238 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
240 static constexpr _Head&
241 _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
243 static constexpr const _Head&
244 _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
250 * Contains the actual implementation of the @c tuple template, stored
251 * as a recursive inheritance hierarchy from the first element (most
252 * derived class) to the last (least derived class). The @c Idx
253 * parameter gives the 0-based index of the element stored at this
254 * point in the hierarchy; we use it to implement a constant-time
257 template<size_t _Idx, typename... _Elements>
261 * Recursive tuple implementation. Here we store the @c Head element
262 * and derive from a @c Tuple_impl containing the remaining elements
263 * (which contains the @c Tail).
265 template<size_t _Idx, typename _Head, typename... _Tail>
266 struct _Tuple_impl<_Idx, _Head, _Tail...>
267 : public _Tuple_impl<_Idx + 1, _Tail...>,
268 private _Head_base<_Idx, _Head>
270 template<size_t, typename...> friend struct _Tuple_impl;
272 typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
273 typedef _Head_base<_Idx, _Head> _Base;
275 static constexpr _Head&
276 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
278 static constexpr const _Head&
279 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
281 static constexpr _Inherited&
282 _M_tail(_Tuple_impl& __t) noexcept { return __t; }
284 static constexpr const _Inherited&
285 _M_tail(const _Tuple_impl& __t) noexcept { return __t; }
287 constexpr _Tuple_impl()
288 : _Inherited(), _Base() { }
291 _Tuple_impl(const _Head& __head, const _Tail&... __tail)
292 : _Inherited(__tail...), _Base(__head)
295 template<typename _UHead, typename... _UTail,
296 typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
298 _Tuple_impl(_UHead&& __head, _UTail&&... __tail)
299 : _Inherited(std::forward<_UTail>(__tail)...),
300 _Base(std::forward<_UHead>(__head))
303 constexpr _Tuple_impl(const _Tuple_impl&) = default;
305 // _GLIBCXX_RESOLVE_LIB_DEFECTS
306 // 2729. Missing SFINAE on std::pair::operator=
307 _Tuple_impl& operator=(const _Tuple_impl&) = delete;
309 _Tuple_impl(_Tuple_impl&&) = default;
311 template<typename... _UElements>
313 _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
314 : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
315 _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
318 template<typename _UHead, typename... _UTails>
320 _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
321 : _Inherited(std::move
322 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
323 _Base(std::forward<_UHead>
324 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
327 #if __cplusplus > 202002L
328 template<typename... _UElements>
330 _Tuple_impl(_Tuple_impl<_Idx, _UElements...>& __in)
331 : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
332 _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
335 template<typename _UHead, typename... _UTails>
337 _Tuple_impl(const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
338 : _Inherited(std::move
339 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
340 _Base(std::forward<const _UHead>
341 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
345 template<typename _Alloc>
347 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
348 : _Inherited(__tag, __a),
349 _Base(__tag, __use_alloc<_Head>(__a))
352 template<typename _Alloc>
354 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
355 const _Head& __head, const _Tail&... __tail)
356 : _Inherited(__tag, __a, __tail...),
357 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head)
360 template<typename _Alloc, typename _UHead, typename... _UTail,
361 typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
363 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
364 _UHead&& __head, _UTail&&... __tail)
365 : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
366 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
367 std::forward<_UHead>(__head))
370 template<typename _Alloc>
372 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
373 const _Tuple_impl& __in)
374 : _Inherited(__tag, __a, _M_tail(__in)),
375 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in))
378 template<typename _Alloc>
380 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
382 : _Inherited(__tag, __a, std::move(_M_tail(__in))),
383 _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
384 std::forward<_Head>(_M_head(__in)))
387 template<typename _Alloc, typename _UHead, typename... _UTails>
389 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
390 const _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
391 : _Inherited(__tag, __a,
392 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
393 _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
394 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
397 template<typename _Alloc, typename _UHead, typename... _UTails>
399 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
400 _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
401 : _Inherited(__tag, __a, std::move
402 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
403 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
405 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
408 #if __cplusplus > 202002L
409 template<typename _Alloc, typename _UHead, typename... _UTails>
411 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
412 _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
413 : _Inherited(__tag, __a,
414 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
415 _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
416 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
419 template<typename _Alloc, typename _UHead, typename... _UTails>
421 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
422 const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
423 : _Inherited(__tag, __a, std::move
424 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
425 _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
426 std::forward<const _UHead>
427 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
431 template<typename... _UElements>
434 _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in)
436 _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
437 _M_tail(*this)._M_assign(
438 _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
441 template<typename _UHead, typename... _UTails>
444 _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
446 _M_head(*this) = std::forward<_UHead>
447 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
448 _M_tail(*this)._M_assign(
449 std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
452 #if __cplusplus > 202002L
453 template<typename... _UElements>
455 _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) const
457 _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
458 _M_tail(*this)._M_assign(
459 _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
462 template<typename _UHead, typename... _UTails>
464 _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) const
466 _M_head(*this) = std::forward<_UHead>
467 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
468 _M_tail(*this)._M_assign(
469 std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
476 _M_swap(_Tuple_impl& __in)
479 swap(_M_head(*this), _M_head(__in));
480 _Inherited::_M_swap(_M_tail(__in));
483 #if __cplusplus > 202002L
485 _M_swap(const _Tuple_impl& __in) const
488 swap(_M_head(*this), _M_head(__in));
489 _Inherited::_M_swap(_M_tail(__in));
494 // Basis case of inheritance recursion.
495 template<size_t _Idx, typename _Head>
496 struct _Tuple_impl<_Idx, _Head>
497 : private _Head_base<_Idx, _Head>
499 template<size_t, typename...> friend struct _Tuple_impl;
501 typedef _Head_base<_Idx, _Head> _Base;
503 static constexpr _Head&
504 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
506 static constexpr const _Head&
507 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
514 _Tuple_impl(const _Head& __head)
518 template<typename _UHead>
520 _Tuple_impl(_UHead&& __head)
521 : _Base(std::forward<_UHead>(__head))
524 constexpr _Tuple_impl(const _Tuple_impl&) = default;
526 // _GLIBCXX_RESOLVE_LIB_DEFECTS
527 // 2729. Missing SFINAE on std::pair::operator=
528 _Tuple_impl& operator=(const _Tuple_impl&) = delete;
530 #if _GLIBCXX_INLINE_VERSION
531 _Tuple_impl(_Tuple_impl&&) = default;
534 _Tuple_impl(_Tuple_impl&& __in)
535 noexcept(is_nothrow_move_constructible<_Head>::value)
536 : _Base(static_cast<_Base&&>(__in))
540 template<typename _UHead>
542 _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in)
543 : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
546 template<typename _UHead>
548 _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in)
549 : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
552 #if __cplusplus > 202002L
553 template<typename _UHead>
555 _Tuple_impl(_Tuple_impl<_Idx, _UHead>& __in)
556 : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
559 template<typename _UHead>
561 _Tuple_impl(const _Tuple_impl<_Idx, _UHead>&& __in)
562 : _Base(std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
566 template<typename _Alloc>
568 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
569 : _Base(__tag, __use_alloc<_Head>(__a))
572 template<typename _Alloc>
574 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
576 : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), __head)
579 template<typename _Alloc, typename _UHead>
581 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
583 : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
584 std::forward<_UHead>(__head))
587 template<typename _Alloc>
589 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
590 const _Tuple_impl& __in)
591 : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), _M_head(__in))
594 template<typename _Alloc>
596 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
598 : _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
599 std::forward<_Head>(_M_head(__in)))
602 template<typename _Alloc, typename _UHead>
604 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
605 const _Tuple_impl<_Idx, _UHead>& __in)
606 : _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
607 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
610 template<typename _Alloc, typename _UHead>
612 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
613 _Tuple_impl<_Idx, _UHead>&& __in)
614 : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
615 std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
618 #if __cplusplus > 202002L
619 template<typename _Alloc, typename _UHead>
621 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
622 _Tuple_impl<_Idx, _UHead>& __in)
623 : _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
624 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
627 template<typename _Alloc, typename _UHead>
629 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
630 const _Tuple_impl<_Idx, _UHead>&& __in)
631 : _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
632 std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
636 template<typename _UHead>
639 _M_assign(const _Tuple_impl<_Idx, _UHead>& __in)
641 _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
644 template<typename _UHead>
647 _M_assign(_Tuple_impl<_Idx, _UHead>&& __in)
650 = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
653 #if __cplusplus > 202002L
654 template<typename _UHead>
656 _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) const
658 _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
661 template<typename _UHead>
663 _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) const
666 = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
673 _M_swap(_Tuple_impl& __in)
676 swap(_M_head(*this), _M_head(__in));
679 #if __cplusplus > 202002L
681 _M_swap(const _Tuple_impl& __in) const
684 swap(_M_head(*this), _M_head(__in));
689 // Concept utility functions, reused in conditionally-explicit
691 template<bool, typename... _Types>
692 struct _TupleConstraints
694 template<typename... _UTypes>
695 using __constructible = __and_<is_constructible<_Types, _UTypes>...>;
697 template<typename... _UTypes>
698 using __convertible = __and_<is_convertible<_UTypes, _Types>...>;
700 // Constraint for a non-explicit constructor.
701 // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
702 // and every Ui is implicitly convertible to Ti.
703 template<typename... _UTypes>
704 static constexpr bool __is_implicitly_constructible()
706 return __and_<__constructible<_UTypes...>,
707 __convertible<_UTypes...>
711 // Constraint for a non-explicit constructor.
712 // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
713 // but not every Ui is implicitly convertible to Ti.
714 template<typename... _UTypes>
715 static constexpr bool __is_explicitly_constructible()
717 return __and_<__constructible<_UTypes...>,
718 __not_<__convertible<_UTypes...>>
722 static constexpr bool __is_implicitly_default_constructible()
724 return __and_<std::__is_implicitly_default_constructible<_Types>...
728 static constexpr bool __is_explicitly_default_constructible()
730 return __and_<is_default_constructible<_Types>...,
732 std::__is_implicitly_default_constructible<_Types>...>
737 // Partial specialization used when a required precondition isn't met,
738 // e.g. when sizeof...(_Types) != sizeof...(_UTypes).
739 template<typename... _Types>
740 struct _TupleConstraints<false, _Types...>
742 template<typename... _UTypes>
743 static constexpr bool __is_implicitly_constructible()
746 template<typename... _UTypes>
747 static constexpr bool __is_explicitly_constructible()
751 /// Primary class template, tuple
752 template<typename... _Elements>
753 class tuple : public _Tuple_impl<0, _Elements...>
755 using _Inherited = _Tuple_impl<0, _Elements...>;
757 #if __cpp_concepts && __cpp_consteval && __cpp_conditional_explicit // >= C++20
758 template<typename... _UTypes>
759 static consteval bool
762 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
763 return __and_v<is_constructible<_Elements, _UTypes>...>;
768 template<typename... _UTypes>
769 static consteval bool
770 __nothrow_constructible()
772 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
773 return __and_v<is_nothrow_constructible<_Elements, _UTypes>...>;
778 template<typename... _UTypes>
779 static consteval bool
782 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
783 return __and_v<is_convertible<_UTypes, _Elements>...>;
788 // _GLIBCXX_RESOLVE_LIB_DEFECTS
789 // 3121. tuple constructor constraints for UTypes&&... overloads
790 template<typename... _UTypes>
791 static consteval bool
792 __disambiguating_constraint()
794 if constexpr (sizeof...(_Elements) != sizeof...(_UTypes))
796 else if constexpr (sizeof...(_Elements) == 1)
798 using _U0 = typename _Nth_type<0, _UTypes...>::type;
799 return !is_same_v<remove_cvref_t<_U0>, tuple>;
801 else if constexpr (sizeof...(_Elements) < 4)
803 using _U0 = typename _Nth_type<0, _UTypes...>::type;
804 if constexpr (!is_same_v<remove_cvref_t<_U0>, allocator_arg_t>)
808 using _T0 = typename _Nth_type<0, _Elements...>::type;
809 return is_same_v<remove_cvref_t<_T0>, allocator_arg_t>;
815 // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
816 // and the single element in Types can be initialized from TUPLE,
817 // or is the same type as tuple_element_t<0, TUPLE>.
818 template<typename _Tuple>
819 static consteval bool
822 if constexpr (sizeof...(_Elements) != 1)
824 else if constexpr (is_same_v<remove_cvref_t<_Tuple>, tuple>)
825 return true; // Should use a copy/move constructor instead.
828 using _Tp = typename _Nth_type<0, _Elements...>::type;
829 if constexpr (is_convertible_v<_Tuple, _Tp>)
831 else if constexpr (is_constructible_v<_Tp, _Tuple>)
837 template<typename... _Up>
838 static consteval bool
841 #if __has_builtin(__reference_constructs_from_temporary)
842 return (__reference_constructs_from_temporary(_Elements, _Up&&)
851 explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
853 noexcept((is_nothrow_default_constructible_v<_Elements> && ...))
854 requires (is_default_constructible_v<_Elements> && ...)
858 constexpr explicit(!__convertible<const _Elements&...>())
859 tuple(const _Elements&... __elements)
860 noexcept(__nothrow_constructible<const _Elements&...>())
861 requires (__constructible<const _Elements&...>())
862 : _Inherited(__elements...)
865 template<typename... _UTypes>
866 requires (__disambiguating_constraint<_UTypes...>())
867 && (__constructible<_UTypes...>())
868 && (!__dangles<_UTypes...>())
869 constexpr explicit(!__convertible<_UTypes...>())
870 tuple(_UTypes&&... __u)
871 noexcept(__nothrow_constructible<_UTypes...>())
872 : _Inherited(std::forward<_UTypes>(__u)...)
875 template<typename... _UTypes>
876 requires (__disambiguating_constraint<_UTypes...>())
877 && (__constructible<_UTypes...>())
878 && (__dangles<_UTypes...>())
879 tuple(_UTypes&&...) = delete;
881 constexpr tuple(const tuple&) = default;
883 constexpr tuple(tuple&&) = default;
885 template<typename... _UTypes>
886 requires (__constructible<const _UTypes&...>())
887 && (!__use_other_ctor<const tuple<_UTypes...>&>())
888 && (!__dangles<const _UTypes&...>())
889 constexpr explicit(!__convertible<const _UTypes&...>())
890 tuple(const tuple<_UTypes...>& __u)
891 noexcept(__nothrow_constructible<const _UTypes&...>())
892 : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
895 template<typename... _UTypes>
896 requires (__constructible<const _UTypes&...>())
897 && (!__use_other_ctor<const tuple<_UTypes...>&>())
898 && (__dangles<const _UTypes&...>())
899 tuple(const tuple<_UTypes...>&) = delete;
901 template<typename... _UTypes>
902 requires (__constructible<_UTypes...>())
903 && (!__use_other_ctor<tuple<_UTypes...>>())
904 && (!__dangles<_UTypes...>())
905 constexpr explicit(!__convertible<_UTypes...>())
906 tuple(tuple<_UTypes...>&& __u)
907 noexcept(__nothrow_constructible<_UTypes...>())
908 : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
911 template<typename... _UTypes>
912 requires (__constructible<_UTypes...>())
913 && (!__use_other_ctor<tuple<_UTypes...>>())
914 && (__dangles<_UTypes...>())
915 tuple(tuple<_UTypes...>&&) = delete;
917 #if __cpp_lib_ranges_zip // >= C++23
918 template<typename... _UTypes>
919 requires (__constructible<_UTypes&...>())
920 && (!__use_other_ctor<tuple<_UTypes...>&>())
921 && (!__dangles<_UTypes&...>())
922 constexpr explicit(!__convertible<_UTypes&...>())
923 tuple(tuple<_UTypes...>& __u)
924 noexcept(__nothrow_constructible<_UTypes&...>())
925 : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
928 template<typename... _UTypes>
929 requires (__constructible<_UTypes&...>())
930 && (!__use_other_ctor<tuple<_UTypes...>&>())
931 && (__dangles<_UTypes&...>())
932 tuple(tuple<_UTypes...>&) = delete;
934 template<typename... _UTypes>
935 requires (__constructible<const _UTypes...>())
936 && (!__use_other_ctor<const tuple<_UTypes...>>())
937 && (!__dangles<const _UTypes...>())
938 constexpr explicit(!__convertible<const _UTypes...>())
939 tuple(const tuple<_UTypes...>&& __u)
940 noexcept(__nothrow_constructible<const _UTypes...>())
941 : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
944 template<typename... _UTypes>
945 requires (__constructible<const _UTypes...>())
946 && (!__use_other_ctor<const tuple<_UTypes...>>())
947 && (__dangles<const _UTypes...>())
948 tuple(const tuple<_UTypes...>&&) = delete;
951 template<typename _U1, typename _U2>
952 requires (sizeof...(_Elements) == 2)
953 && (__constructible<const _U1&, const _U2&>())
954 && (!__dangles<const _U1&, const _U2&>())
955 constexpr explicit(!__convertible<const _U1&, const _U2&>())
956 tuple(const pair<_U1, _U2>& __u)
957 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
958 : _Inherited(__u.first, __u.second)
961 template<typename _U1, typename _U2>
962 requires (sizeof...(_Elements) == 2)
963 && (__constructible<const _U1&, const _U2&>())
964 && (__dangles<const _U1&, const _U2&>())
965 tuple(const pair<_U1, _U2>&) = delete;
967 template<typename _U1, typename _U2>
968 requires (sizeof...(_Elements) == 2)
969 && (__constructible<_U1, _U2>())
970 && (!__dangles<_U1, _U2>())
971 constexpr explicit(!__convertible<_U1, _U2>())
972 tuple(pair<_U1, _U2>&& __u)
973 noexcept(__nothrow_constructible<_U1, _U2>())
974 : _Inherited(std::forward<_U1>(__u.first),
975 std::forward<_U2>(__u.second))
978 template<typename _U1, typename _U2>
979 requires (sizeof...(_Elements) == 2)
980 && (__constructible<_U1, _U2>())
981 && (__dangles<_U1, _U2>())
982 tuple(pair<_U1, _U2>&&) = delete;
984 #if __cpp_lib_ranges_zip // >= C++23
985 template<typename _U1, typename _U2>
986 requires (sizeof...(_Elements) == 2)
987 && (__constructible<_U1&, _U2&>())
988 && (!__dangles<_U1&, _U2&>())
989 constexpr explicit(!__convertible<_U1&, _U2&>())
990 tuple(pair<_U1, _U2>& __u)
991 noexcept(__nothrow_constructible<_U1&, _U2&>())
992 : _Inherited(__u.first, __u.second)
995 template<typename _U1, typename _U2>
996 requires (sizeof...(_Elements) == 2)
997 && (__constructible<_U1&, _U2&>())
998 && (__dangles<_U1&, _U2&>())
999 tuple(pair<_U1, _U2>&) = delete;
1001 template<typename _U1, typename _U2>
1002 requires (sizeof...(_Elements) == 2)
1003 && (__constructible<const _U1, const _U2>())
1004 && (!__dangles<const _U1, const _U2>())
1005 constexpr explicit(!__convertible<const _U1, const _U2>())
1006 tuple(const pair<_U1, _U2>&& __u)
1007 noexcept(__nothrow_constructible<const _U1, const _U2>())
1008 : _Inherited(std::forward<const _U1>(__u.first),
1009 std::forward<const _U2>(__u.second))
1012 template<typename _U1, typename _U2>
1013 requires (sizeof...(_Elements) == 2)
1014 && (__constructible<const _U1, const _U2>())
1015 && (__dangles<const _U1, const _U2>())
1016 tuple(const pair<_U1, _U2>&&) = delete;
1019 #if 0 && __cpp_lib_tuple_like // >= C++23
1020 template<__tuple_like _UTuple>
1021 constexpr explicit(...)
1022 tuple(_UTuple&& __u);
1025 // Allocator-extended constructors.
1027 template<typename _Alloc>
1029 explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
1030 tuple(allocator_arg_t __tag, const _Alloc& __a)
1031 requires (is_default_constructible_v<_Elements> && ...)
1032 : _Inherited(__tag, __a)
1035 template<typename _Alloc>
1036 constexpr explicit(!__convertible<const _Elements&...>())
1037 tuple(allocator_arg_t __tag, const _Alloc& __a,
1038 const _Elements&... __elements)
1039 requires (__constructible<const _Elements&...>())
1040 : _Inherited(__tag, __a, __elements...)
1043 template<typename _Alloc, typename... _UTypes>
1044 requires (__disambiguating_constraint<_UTypes...>())
1045 && (__constructible<_UTypes...>())
1046 && (!__dangles<_UTypes...>())
1047 constexpr explicit(!__convertible<_UTypes...>())
1048 tuple(allocator_arg_t __tag, const _Alloc& __a, _UTypes&&... __u)
1049 : _Inherited(__tag, __a, std::forward<_UTypes>(__u)...)
1052 template<typename _Alloc, typename... _UTypes>
1053 requires (__disambiguating_constraint<_UTypes...>())
1054 && (__constructible<_UTypes...>())
1055 && (__dangles<_UTypes...>())
1056 tuple(allocator_arg_t, const _Alloc&, _UTypes&&...) = delete;
1058 template<typename _Alloc>
1060 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __u)
1061 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__u))
1064 template<typename _Alloc>
1065 requires (__constructible<_Elements...>())
1067 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __u)
1068 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__u))
1071 template<typename _Alloc, typename... _UTypes>
1072 requires (__constructible<const _UTypes&...>())
1073 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1074 && (!__dangles<const _UTypes&...>())
1075 constexpr explicit(!__convertible<const _UTypes&...>())
1076 tuple(allocator_arg_t __tag, const _Alloc& __a,
1077 const tuple<_UTypes...>& __u)
1078 : _Inherited(__tag, __a,
1079 static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1082 template<typename _Alloc, typename... _UTypes>
1083 requires (__constructible<const _UTypes&...>())
1084 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1085 && (__dangles<const _UTypes&...>())
1086 tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&) = delete;
1088 template<typename _Alloc, typename... _UTypes>
1089 requires (__constructible<_UTypes...>())
1090 && (!__use_other_ctor<tuple<_UTypes...>>())
1091 && (!__dangles<_UTypes...>())
1092 constexpr explicit(!__use_other_ctor<tuple<_UTypes...>>())
1093 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>&& __u)
1094 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1097 template<typename _Alloc, typename... _UTypes>
1098 requires (__constructible<_UTypes...>())
1099 && (!__use_other_ctor<tuple<_UTypes...>>())
1100 && (__dangles<_UTypes...>())
1101 tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&&) = delete;
1103 #if __cpp_lib_ranges_zip // >= C++23
1104 template<typename _Alloc, typename... _UTypes>
1105 requires (__constructible<_UTypes&...>())
1106 && (!__use_other_ctor<tuple<_UTypes...>&>())
1107 && (!__dangles<_UTypes&...>())
1108 constexpr explicit(!__convertible<_UTypes&...>())
1109 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>& __u)
1110 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1113 template<typename _Alloc, typename... _UTypes>
1114 requires (__constructible<_UTypes&...>())
1115 && (!__use_other_ctor<tuple<_UTypes...>&>())
1116 && (__dangles<_UTypes&...>())
1117 tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&) = delete;
1119 template<typename _Alloc, typename... _UTypes>
1120 requires (__constructible<const _UTypes...>())
1121 && (!__use_other_ctor<const tuple<_UTypes...>>())
1122 && (!__dangles<const _UTypes...>())
1123 constexpr explicit(!__convertible<const _UTypes...>())
1124 tuple(allocator_arg_t __tag, const _Alloc& __a,
1125 const tuple<_UTypes...>&& __u)
1126 : _Inherited(__tag, __a,
1127 static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1130 template<typename _Alloc, typename... _UTypes>
1131 requires (__constructible<const _UTypes...>())
1132 && (!__use_other_ctor<const tuple<_UTypes...>>())
1133 && (__dangles<const _UTypes...>())
1134 tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&&) = delete;
1137 template<typename _Alloc, typename _U1, typename _U2>
1138 requires (sizeof...(_Elements) == 2)
1139 && (__constructible<const _U1&, const _U2&>())
1140 && (!__dangles<const _U1&, const _U2&>())
1141 constexpr explicit(!__convertible<const _U1&, const _U2&>())
1142 tuple(allocator_arg_t __tag, const _Alloc& __a,
1143 const pair<_U1, _U2>& __u)
1144 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1145 : _Inherited(__tag, __a, __u.first, __u.second)
1148 template<typename _Alloc, typename _U1, typename _U2>
1149 requires (sizeof...(_Elements) == 2)
1150 && (__constructible<const _U1&, const _U2&>())
1151 && (__dangles<const _U1&, const _U2&>())
1152 tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&) = delete;
1154 template<typename _Alloc, typename _U1, typename _U2>
1155 requires (sizeof...(_Elements) == 2)
1156 && (__constructible<_U1, _U2>())
1157 && (!__dangles<_U1, _U2>())
1158 constexpr explicit(!__convertible<_U1, _U2>())
1159 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __u)
1160 noexcept(__nothrow_constructible<_U1, _U2>())
1161 : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1164 template<typename _Alloc, typename _U1, typename _U2>
1165 requires (sizeof...(_Elements) == 2)
1166 && (__constructible<_U1, _U2>())
1167 && (__dangles<_U1, _U2>())
1168 tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&) = delete;
1170 #if __cpp_lib_ranges_zip // >= C++23
1171 template<typename _Alloc, typename _U1, typename _U2>
1172 requires (sizeof...(_Elements) == 2)
1173 && (__constructible<_U1&, _U2&>())
1174 && (!__dangles<_U1&, _U2&>())
1175 constexpr explicit(!__convertible<_U1&, _U2&>())
1176 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>& __u)
1177 noexcept(__nothrow_constructible<_U1&, _U2&>())
1178 : _Inherited(__tag, __a, __u.first, __u.second)
1181 template<typename _Alloc, typename _U1, typename _U2>
1182 requires (sizeof...(_Elements) == 2)
1183 && (__constructible<_U1&, _U2&>())
1184 && (__dangles<_U1&, _U2&>())
1185 tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&) = delete;
1187 template<typename _Alloc, typename _U1, typename _U2>
1188 requires (sizeof...(_Elements) == 2)
1189 && (__constructible<const _U1, const _U2>())
1190 && (!__dangles<const _U1, const _U2>())
1191 constexpr explicit(!__convertible<const _U1, const _U2>())
1192 tuple(allocator_arg_t __tag, const _Alloc& __a,
1193 const pair<_U1, _U2>&& __u)
1194 noexcept(__nothrow_constructible<const _U1, const _U2>())
1195 : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1198 template<typename _Alloc, typename _U1, typename _U2>
1199 requires (sizeof...(_Elements) == 2)
1200 && (__constructible<const _U1, const _U2>())
1201 && (__dangles<const _U1, const _U2>())
1202 tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&&) = delete;
1205 #if 0 && __cpp_lib_tuple_like // >= C++23
1206 template<typename _Alloc, __tuple_like _UTuple>
1207 constexpr explicit(...)
1208 tuple(allocator_arg_t __tag, const _Alloc& __a, _UTuple&& __u);
1211 #else // !(concepts && conditional_explicit)
1213 template<bool _Cond>
1214 using _TCC = _TupleConstraints<_Cond, _Elements...>;
1216 // Constraint for non-explicit default constructor
1217 template<bool _Dummy>
1218 using _ImplicitDefaultCtor = __enable_if_t<
1219 _TCC<_Dummy>::__is_implicitly_default_constructible(),
1222 // Constraint for explicit default constructor
1223 template<bool _Dummy>
1224 using _ExplicitDefaultCtor = __enable_if_t<
1225 _TCC<_Dummy>::__is_explicitly_default_constructible(),
1228 // Constraint for non-explicit constructors
1229 template<bool _Cond, typename... _Args>
1230 using _ImplicitCtor = __enable_if_t<
1231 _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
1234 // Constraint for non-explicit constructors
1235 template<bool _Cond, typename... _Args>
1236 using _ExplicitCtor = __enable_if_t<
1237 _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
1240 // Condition for noexcept-specifier of a constructor.
1241 template<typename... _UElements>
1242 static constexpr bool __nothrow_constructible()
1245 __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
1248 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1.
1249 template<typename _Up>
1250 static constexpr bool __valid_args()
1252 return sizeof...(_Elements) == 1
1253 && !is_same<tuple, __remove_cvref_t<_Up>>::value;
1256 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1.
1257 template<typename, typename, typename... _Tail>
1258 static constexpr bool __valid_args()
1259 { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); }
1261 /* Constraint for constructors with a tuple<UTypes...> parameter ensures
1262 * that the constructor is only viable when it would not interfere with
1263 * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&).
1264 * Such constructors are only viable if:
1265 * either sizeof...(Types) != 1,
1266 * or (when Types... expands to T and UTypes... expands to U)
1267 * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>,
1268 * and is_same_v<T, U> are all false.
1270 template<typename _Tuple, typename = tuple,
1271 typename = __remove_cvref_t<_Tuple>>
1272 struct _UseOtherCtor
1275 // If TUPLE is convertible to the single element in *this,
1276 // then TUPLE should match tuple(UTypes&&...) instead.
1277 template<typename _Tuple, typename _Tp, typename _Up>
1278 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>>
1279 : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>::type
1281 // If TUPLE and *this each have a single element of the same type,
1282 // then TUPLE should match a copy/move constructor instead.
1283 template<typename _Tuple, typename _Tp>
1284 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>>
1288 // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
1289 // and the single element in Types can be initialized from TUPLE,
1290 // or is the same type as tuple_element_t<0, TUPLE>.
1291 template<typename _Tuple>
1292 static constexpr bool __use_other_ctor()
1293 { return _UseOtherCtor<_Tuple>::value; }
1295 /// @cond undocumented
1296 #undef __glibcxx_no_dangling_refs
1297 #if __has_builtin(__reference_constructs_from_temporary) \
1298 && defined _GLIBCXX_DEBUG
1299 // Error if construction from U... would create a dangling ref.
1300 # if __cpp_fold_expressions
1301 # define __glibcxx_dangling_refs(U) \
1302 (__reference_constructs_from_temporary(_Elements, U) && ...)
1304 # define __glibcxx_dangling_refs(U) \
1305 __or_<__bool_constant<__reference_constructs_from_temporary(_Elements, U) \
1308 # define __glibcxx_no_dangling_refs(U) \
1309 static_assert(!__glibcxx_dangling_refs(U), \
1310 "std::tuple constructor creates a dangling reference")
1312 # define __glibcxx_no_dangling_refs(U)
1317 template<typename _Dummy = void,
1318 _ImplicitDefaultCtor<is_void<_Dummy>::value> = true>
1321 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1324 template<typename _Dummy = void,
1325 _ExplicitDefaultCtor<is_void<_Dummy>::value> = false>
1328 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1331 template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1332 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1334 tuple(const _Elements&... __elements)
1335 noexcept(__nothrow_constructible<const _Elements&...>())
1336 : _Inherited(__elements...) { }
1338 template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1339 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1341 tuple(const _Elements&... __elements)
1342 noexcept(__nothrow_constructible<const _Elements&...>())
1343 : _Inherited(__elements...) { }
1345 template<typename... _UElements,
1346 bool _Valid = __valid_args<_UElements...>(),
1347 _ImplicitCtor<_Valid, _UElements...> = true>
1349 tuple(_UElements&&... __elements)
1350 noexcept(__nothrow_constructible<_UElements...>())
1351 : _Inherited(std::forward<_UElements>(__elements)...)
1352 { __glibcxx_no_dangling_refs(_UElements&&); }
1354 template<typename... _UElements,
1355 bool _Valid = __valid_args<_UElements...>(),
1356 _ExplicitCtor<_Valid, _UElements...> = false>
1358 tuple(_UElements&&... __elements)
1359 noexcept(__nothrow_constructible<_UElements...>())
1360 : _Inherited(std::forward<_UElements>(__elements)...)
1361 { __glibcxx_no_dangling_refs(_UElements&&); }
1363 constexpr tuple(const tuple&) = default;
1365 constexpr tuple(tuple&&) = default;
1367 template<typename... _UElements,
1368 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1369 && !__use_other_ctor<const tuple<_UElements...>&>(),
1370 _ImplicitCtor<_Valid, const _UElements&...> = true>
1372 tuple(const tuple<_UElements...>& __in)
1373 noexcept(__nothrow_constructible<const _UElements&...>())
1374 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1375 { __glibcxx_no_dangling_refs(const _UElements&); }
1377 template<typename... _UElements,
1378 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1379 && !__use_other_ctor<const tuple<_UElements...>&>(),
1380 _ExplicitCtor<_Valid, const _UElements&...> = false>
1382 tuple(const tuple<_UElements...>& __in)
1383 noexcept(__nothrow_constructible<const _UElements&...>())
1384 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1385 { __glibcxx_no_dangling_refs(const _UElements&); }
1387 template<typename... _UElements,
1388 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1389 && !__use_other_ctor<tuple<_UElements...>&&>(),
1390 _ImplicitCtor<_Valid, _UElements...> = true>
1392 tuple(tuple<_UElements...>&& __in)
1393 noexcept(__nothrow_constructible<_UElements...>())
1394 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1395 { __glibcxx_no_dangling_refs(_UElements&&); }
1397 template<typename... _UElements,
1398 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1399 && !__use_other_ctor<tuple<_UElements...>&&>(),
1400 _ExplicitCtor<_Valid, _UElements...> = false>
1402 tuple(tuple<_UElements...>&& __in)
1403 noexcept(__nothrow_constructible<_UElements...>())
1404 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1405 { __glibcxx_no_dangling_refs(_UElements&&); }
1407 // Allocator-extended constructors.
1409 template<typename _Alloc,
1410 _ImplicitDefaultCtor<is_object<_Alloc>::value> = true>
1411 _GLIBCXX20_CONSTEXPR
1412 tuple(allocator_arg_t __tag, const _Alloc& __a)
1413 : _Inherited(__tag, __a) { }
1415 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1416 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1417 _GLIBCXX20_CONSTEXPR
1418 tuple(allocator_arg_t __tag, const _Alloc& __a,
1419 const _Elements&... __elements)
1420 : _Inherited(__tag, __a, __elements...) { }
1422 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1423 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1424 _GLIBCXX20_CONSTEXPR
1426 tuple(allocator_arg_t __tag, const _Alloc& __a,
1427 const _Elements&... __elements)
1428 : _Inherited(__tag, __a, __elements...) { }
1430 template<typename _Alloc, typename... _UElements,
1431 bool _Valid = __valid_args<_UElements...>(),
1432 _ImplicitCtor<_Valid, _UElements...> = true>
1433 _GLIBCXX20_CONSTEXPR
1434 tuple(allocator_arg_t __tag, const _Alloc& __a,
1435 _UElements&&... __elements)
1436 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1437 { __glibcxx_no_dangling_refs(_UElements&&); }
1439 template<typename _Alloc, typename... _UElements,
1440 bool _Valid = __valid_args<_UElements...>(),
1441 _ExplicitCtor<_Valid, _UElements...> = false>
1442 _GLIBCXX20_CONSTEXPR
1444 tuple(allocator_arg_t __tag, const _Alloc& __a,
1445 _UElements&&... __elements)
1446 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1447 { __glibcxx_no_dangling_refs(_UElements&&); }
1449 template<typename _Alloc>
1450 _GLIBCXX20_CONSTEXPR
1451 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1452 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1454 template<typename _Alloc>
1455 _GLIBCXX20_CONSTEXPR
1456 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1457 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1459 template<typename _Alloc, typename... _UElements,
1460 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1461 && !__use_other_ctor<const tuple<_UElements...>&>(),
1462 _ImplicitCtor<_Valid, const _UElements&...> = true>
1463 _GLIBCXX20_CONSTEXPR
1464 tuple(allocator_arg_t __tag, const _Alloc& __a,
1465 const tuple<_UElements...>& __in)
1466 : _Inherited(__tag, __a,
1467 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1468 { __glibcxx_no_dangling_refs(const _UElements&); }
1470 template<typename _Alloc, typename... _UElements,
1471 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1472 && !__use_other_ctor<const tuple<_UElements...>&>(),
1473 _ExplicitCtor<_Valid, const _UElements&...> = false>
1474 _GLIBCXX20_CONSTEXPR
1476 tuple(allocator_arg_t __tag, const _Alloc& __a,
1477 const tuple<_UElements...>& __in)
1478 : _Inherited(__tag, __a,
1479 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1480 { __glibcxx_no_dangling_refs(const _UElements&); }
1482 template<typename _Alloc, typename... _UElements,
1483 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1484 && !__use_other_ctor<tuple<_UElements...>&&>(),
1485 _ImplicitCtor<_Valid, _UElements...> = true>
1486 _GLIBCXX20_CONSTEXPR
1487 tuple(allocator_arg_t __tag, const _Alloc& __a,
1488 tuple<_UElements...>&& __in)
1489 : _Inherited(__tag, __a,
1490 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1491 { __glibcxx_no_dangling_refs(_UElements&&); }
1493 template<typename _Alloc, typename... _UElements,
1494 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1495 && !__use_other_ctor<tuple<_UElements...>&&>(),
1496 _ExplicitCtor<_Valid, _UElements...> = false>
1497 _GLIBCXX20_CONSTEXPR
1499 tuple(allocator_arg_t __tag, const _Alloc& __a,
1500 tuple<_UElements...>&& __in)
1501 : _Inherited(__tag, __a,
1502 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1503 { __glibcxx_no_dangling_refs(_UElements&&); }
1504 #endif // concepts && conditional_explicit
1508 #if __cpp_concepts && __cpp_consteval // >= C++20
1510 template<typename... _UTypes>
1511 static consteval bool
1514 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1515 return __and_v<is_assignable<_Elements&, _UTypes>...>;
1520 template<typename... _UTypes>
1521 static consteval bool
1522 __nothrow_assignable()
1524 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1525 return __and_v<is_nothrow_assignable<_Elements&, _UTypes>...>;
1530 #if __cpp_lib_ranges_zip // >= C++23
1531 template<typename... _UTypes>
1532 static consteval bool
1533 __const_assignable()
1535 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1536 return __and_v<is_assignable<const _Elements&, _UTypes>...>;
1544 tuple& operator=(const tuple& __u) = delete;
1547 operator=(const tuple& __u)
1548 noexcept(__nothrow_assignable<const _Elements&...>())
1549 requires (__assignable<const _Elements&...>())
1551 this->_M_assign(__u);
1556 operator=(tuple&& __u)
1557 noexcept(__nothrow_assignable<_Elements...>())
1558 requires (__assignable<_Elements...>())
1560 this->_M_assign(std::move(__u));
1564 template<typename... _UTypes>
1565 requires (__assignable<const _UTypes&...>())
1567 operator=(const tuple<_UTypes...>& __u)
1568 noexcept(__nothrow_assignable<const _UTypes&...>())
1570 this->_M_assign(__u);
1574 template<typename... _UTypes>
1575 requires (__assignable<_UTypes...>())
1577 operator=(tuple<_UTypes...>&& __u)
1578 noexcept(__nothrow_assignable<_UTypes...>())
1580 this->_M_assign(std::move(__u));
1584 #if __cpp_lib_ranges_zip // >= C++23
1585 constexpr const tuple&
1586 operator=(const tuple& __u) const
1587 requires (__const_assignable<const _Elements&...>())
1589 this->_M_assign(__u);
1593 constexpr const tuple&
1594 operator=(tuple&& __u) const
1595 requires (__const_assignable<_Elements...>())
1597 this->_M_assign(std::move(__u));
1601 template<typename... _UTypes>
1602 constexpr const tuple&
1603 operator=(const tuple<_UTypes...>& __u) const
1604 requires (__const_assignable<const _UTypes&...>())
1606 this->_M_assign(__u);
1610 template<typename... _UTypes>
1611 constexpr const tuple&
1612 operator=(tuple<_UTypes...>&& __u) const
1613 requires (__const_assignable<_UTypes...>())
1615 this->_M_assign(std::move(__u));
1620 template<typename _U1, typename _U2>
1621 requires (__assignable<const _U1&, const _U2&>())
1623 operator=(const pair<_U1, _U2>& __u)
1624 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1626 this->_M_head(*this) = __u.first;
1627 this->_M_tail(*this)._M_head(*this) = __u.second;
1631 template<typename _U1, typename _U2>
1632 requires (__assignable<_U1, _U2>())
1634 operator=(pair<_U1, _U2>&& __u)
1635 noexcept(__nothrow_assignable<_U1, _U2>())
1637 this->_M_head(*this) = std::forward<_U1>(__u.first);
1638 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1642 #if __cpp_lib_ranges_zip // >= C++23
1643 template<typename _U1, typename _U2>
1644 requires (__const_assignable<const _U1&, const _U2>())
1645 constexpr const tuple&
1646 operator=(const pair<_U1, _U2>& __u) const
1648 this->_M_head(*this) = __u.first;
1649 this->_M_tail(*this)._M_head(*this) = __u.second;
1653 template<typename _U1, typename _U2>
1654 requires (__const_assignable<_U1, _U2>())
1655 constexpr const tuple&
1656 operator=(pair<_U1, _U2>&& __u) const
1658 this->_M_head(*this) = std::forward<_U1>(__u.first);
1659 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1664 #if 0 && __cpp_lib_tuple_like // >= C++23
1665 template<__tuple_like _UTuple>
1667 operator=(_UTuple&& __u);
1669 template<__tuple_like _UTuple>
1671 operator=(_UTuple&& __u) const;
1674 #else // ! (concepts && consteval)
1677 template<typename... _UElements>
1679 __enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
1681 { return __and_<is_assignable<_Elements&, _UElements>...>::value; }
1683 // Condition for noexcept-specifier of an assignment operator.
1684 template<typename... _UElements>
1685 static constexpr bool __nothrow_assignable()
1688 __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
1693 _GLIBCXX20_CONSTEXPR
1695 operator=(__conditional_t<__assignable<const _Elements&...>(),
1697 const __nonesuch&> __in)
1698 noexcept(__nothrow_assignable<const _Elements&...>())
1700 this->_M_assign(__in);
1704 _GLIBCXX20_CONSTEXPR
1706 operator=(__conditional_t<__assignable<_Elements...>(),
1709 noexcept(__nothrow_assignable<_Elements...>())
1711 this->_M_assign(std::move(__in));
1715 template<typename... _UElements>
1716 _GLIBCXX20_CONSTEXPR
1717 __enable_if_t<__assignable<const _UElements&...>(), tuple&>
1718 operator=(const tuple<_UElements...>& __in)
1719 noexcept(__nothrow_assignable<const _UElements&...>())
1721 this->_M_assign(__in);
1725 template<typename... _UElements>
1726 _GLIBCXX20_CONSTEXPR
1727 __enable_if_t<__assignable<_UElements...>(), tuple&>
1728 operator=(tuple<_UElements...>&& __in)
1729 noexcept(__nothrow_assignable<_UElements...>())
1731 this->_M_assign(std::move(__in));
1734 #endif // concepts && consteval
1737 _GLIBCXX20_CONSTEXPR
1740 noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
1741 { _Inherited::_M_swap(__in); }
1743 #if __cpp_lib_ranges_zip // >= C++23
1744 // As an extension, we constrain the const swap member function in order
1745 // to continue accepting explicit instantiation of tuples whose elements
1746 // are not all const swappable. Without this constraint, such an
1747 // explicit instantiation would also instantiate the ill-formed body of
1748 // this function and yield a hard error. This constraint shouldn't
1749 // affect the behavior of valid programs.
1751 swap(const tuple& __in) const
1752 noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
1753 requires (is_swappable_v<const _Elements> && ...)
1754 { _Inherited::_M_swap(__in); }
1758 #if __cpp_deduction_guides >= 201606
1759 template<typename... _UTypes>
1760 tuple(_UTypes...) -> tuple<_UTypes...>;
1761 template<typename _T1, typename _T2>
1762 tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
1763 template<typename _Alloc, typename... _UTypes>
1764 tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
1765 template<typename _Alloc, typename _T1, typename _T2>
1766 tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
1767 template<typename _Alloc, typename... _UTypes>
1768 tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
1771 // Explicit specialization, zero-element tuple.
1776 _GLIBCXX20_CONSTEXPR
1777 void swap(tuple&) noexcept { /* no-op */ }
1778 #if __cplusplus > 202002L
1779 constexpr void swap(const tuple&) const noexcept { /* no-op */ }
1781 // We need the default since we're going to define no-op
1782 // allocator constructors.
1784 // No-op allocator constructors.
1785 template<typename _Alloc>
1786 _GLIBCXX20_CONSTEXPR
1787 tuple(allocator_arg_t, const _Alloc&) noexcept { }
1788 template<typename _Alloc>
1789 _GLIBCXX20_CONSTEXPR
1790 tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
1793 #if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20
1794 /// Partial specialization, 2-element tuple.
1795 /// Includes construction and assignment from a pair.
1796 template<typename _T1, typename _T2>
1797 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
1799 typedef _Tuple_impl<0, _T1, _T2> _Inherited;
1801 // Constraint for non-explicit default constructor
1802 template<bool _Dummy, typename _U1, typename _U2>
1803 using _ImplicitDefaultCtor = __enable_if_t<
1804 _TupleConstraints<_Dummy, _U1, _U2>::
1805 __is_implicitly_default_constructible(),
1808 // Constraint for explicit default constructor
1809 template<bool _Dummy, typename _U1, typename _U2>
1810 using _ExplicitDefaultCtor = __enable_if_t<
1811 _TupleConstraints<_Dummy, _U1, _U2>::
1812 __is_explicitly_default_constructible(),
1815 template<bool _Dummy>
1816 using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
1818 // Constraint for non-explicit constructors
1819 template<bool _Cond, typename _U1, typename _U2>
1820 using _ImplicitCtor = __enable_if_t<
1821 _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
1824 // Constraint for non-explicit constructors
1825 template<bool _Cond, typename _U1, typename _U2>
1826 using _ExplicitCtor = __enable_if_t<
1827 _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
1830 template<typename _U1, typename _U2>
1831 static constexpr bool __assignable()
1833 return __and_<is_assignable<_T1&, _U1>,
1834 is_assignable<_T2&, _U2>>::value;
1837 template<typename _U1, typename _U2>
1838 static constexpr bool __nothrow_assignable()
1840 return __and_<is_nothrow_assignable<_T1&, _U1>,
1841 is_nothrow_assignable<_T2&, _U2>>::value;
1844 template<typename _U1, typename _U2>
1845 static constexpr bool __nothrow_constructible()
1847 return __and_<is_nothrow_constructible<_T1, _U1>,
1848 is_nothrow_constructible<_T2, _U2>>::value;
1851 static constexpr bool __nothrow_default_constructible()
1853 return __and_<is_nothrow_default_constructible<_T1>,
1854 is_nothrow_default_constructible<_T2>>::value;
1857 template<typename _U1>
1858 static constexpr bool __is_alloc_arg()
1859 { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
1861 /// @cond undocumented
1862 #undef __glibcxx_no_dangling_refs
1863 // Error if construction from _U1 and _U2 would create a dangling ref.
1864 #if __has_builtin(__reference_constructs_from_temporary) \
1865 && defined _GLIBCXX_DEBUG
1866 # define __glibcxx_no_dangling_refs(_U1, _U2) \
1867 static_assert(!__reference_constructs_from_temporary(_T1, _U1) \
1868 && !__reference_constructs_from_temporary(_T2, _U2), \
1869 "std::tuple constructor creates a dangling reference")
1871 # define __glibcxx_no_dangling_refs(_U1, _U2)
1876 template<bool _Dummy = true,
1877 _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
1880 noexcept(__nothrow_default_constructible())
1883 template<bool _Dummy = true,
1884 _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
1887 noexcept(__nothrow_default_constructible())
1890 template<bool _Dummy = true,
1891 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
1893 tuple(const _T1& __a1, const _T2& __a2)
1894 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
1895 : _Inherited(__a1, __a2) { }
1897 template<bool _Dummy = true,
1898 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
1900 tuple(const _T1& __a1, const _T2& __a2)
1901 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
1902 : _Inherited(__a1, __a2) { }
1904 template<typename _U1, typename _U2,
1905 _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
1907 tuple(_U1&& __a1, _U2&& __a2)
1908 noexcept(__nothrow_constructible<_U1, _U2>())
1909 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
1910 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
1912 template<typename _U1, typename _U2,
1913 _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
1915 tuple(_U1&& __a1, _U2&& __a2)
1916 noexcept(__nothrow_constructible<_U1, _U2>())
1917 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
1918 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
1920 constexpr tuple(const tuple&) = default;
1922 constexpr tuple(tuple&&) = default;
1924 template<typename _U1, typename _U2,
1925 _ImplicitCtor<true, const _U1&, const _U2&> = true>
1927 tuple(const tuple<_U1, _U2>& __in)
1928 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1929 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
1930 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
1932 template<typename _U1, typename _U2,
1933 _ExplicitCtor<true, const _U1&, const _U2&> = false>
1935 tuple(const tuple<_U1, _U2>& __in)
1936 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1937 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
1938 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
1940 template<typename _U1, typename _U2,
1941 _ImplicitCtor<true, _U1, _U2> = true>
1943 tuple(tuple<_U1, _U2>&& __in)
1944 noexcept(__nothrow_constructible<_U1, _U2>())
1945 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
1946 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
1948 template<typename _U1, typename _U2,
1949 _ExplicitCtor<true, _U1, _U2> = false>
1951 tuple(tuple<_U1, _U2>&& __in)
1952 noexcept(__nothrow_constructible<_U1, _U2>())
1953 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
1954 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
1956 template<typename _U1, typename _U2,
1957 _ImplicitCtor<true, const _U1&, const _U2&> = true>
1959 tuple(const pair<_U1, _U2>& __in)
1960 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1961 : _Inherited(__in.first, __in.second)
1962 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
1964 template<typename _U1, typename _U2,
1965 _ExplicitCtor<true, const _U1&, const _U2&> = false>
1967 tuple(const pair<_U1, _U2>& __in)
1968 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1969 : _Inherited(__in.first, __in.second)
1970 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
1972 template<typename _U1, typename _U2,
1973 _ImplicitCtor<true, _U1, _U2> = true>
1975 tuple(pair<_U1, _U2>&& __in)
1976 noexcept(__nothrow_constructible<_U1, _U2>())
1977 : _Inherited(std::forward<_U1>(__in.first),
1978 std::forward<_U2>(__in.second))
1979 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
1981 template<typename _U1, typename _U2,
1982 _ExplicitCtor<true, _U1, _U2> = false>
1984 tuple(pair<_U1, _U2>&& __in)
1985 noexcept(__nothrow_constructible<_U1, _U2>())
1986 : _Inherited(std::forward<_U1>(__in.first),
1987 std::forward<_U2>(__in.second))
1988 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
1990 // Allocator-extended constructors.
1992 template<typename _Alloc,
1993 _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
1994 _GLIBCXX20_CONSTEXPR
1995 tuple(allocator_arg_t __tag, const _Alloc& __a)
1996 : _Inherited(__tag, __a) { }
1998 template<typename _Alloc, bool _Dummy = true,
1999 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2000 _GLIBCXX20_CONSTEXPR
2001 tuple(allocator_arg_t __tag, const _Alloc& __a,
2002 const _T1& __a1, const _T2& __a2)
2003 : _Inherited(__tag, __a, __a1, __a2) { }
2005 template<typename _Alloc, bool _Dummy = true,
2006 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2008 _GLIBCXX20_CONSTEXPR
2009 tuple(allocator_arg_t __tag, const _Alloc& __a,
2010 const _T1& __a1, const _T2& __a2)
2011 : _Inherited(__tag, __a, __a1, __a2) { }
2013 template<typename _Alloc, typename _U1, typename _U2,
2014 _ImplicitCtor<true, _U1, _U2> = true>
2015 _GLIBCXX20_CONSTEXPR
2016 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
2017 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2018 std::forward<_U2>(__a2))
2019 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2021 template<typename _Alloc, typename _U1, typename _U2,
2022 _ExplicitCtor<true, _U1, _U2> = false>
2024 _GLIBCXX20_CONSTEXPR
2025 tuple(allocator_arg_t __tag, const _Alloc& __a,
2026 _U1&& __a1, _U2&& __a2)
2027 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2028 std::forward<_U2>(__a2))
2029 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2031 template<typename _Alloc>
2032 _GLIBCXX20_CONSTEXPR
2033 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
2034 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
2036 template<typename _Alloc>
2037 _GLIBCXX20_CONSTEXPR
2038 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
2039 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
2041 template<typename _Alloc, typename _U1, typename _U2,
2042 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2043 _GLIBCXX20_CONSTEXPR
2044 tuple(allocator_arg_t __tag, const _Alloc& __a,
2045 const tuple<_U1, _U2>& __in)
2046 : _Inherited(__tag, __a,
2047 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2048 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2050 template<typename _Alloc, typename _U1, typename _U2,
2051 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2053 _GLIBCXX20_CONSTEXPR
2054 tuple(allocator_arg_t __tag, const _Alloc& __a,
2055 const tuple<_U1, _U2>& __in)
2056 : _Inherited(__tag, __a,
2057 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2058 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2060 template<typename _Alloc, typename _U1, typename _U2,
2061 _ImplicitCtor<true, _U1, _U2> = true>
2062 _GLIBCXX20_CONSTEXPR
2063 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2064 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2065 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2067 template<typename _Alloc, typename _U1, typename _U2,
2068 _ExplicitCtor<true, _U1, _U2> = false>
2070 _GLIBCXX20_CONSTEXPR
2071 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2072 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2073 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2075 template<typename _Alloc, typename _U1, typename _U2,
2076 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2077 _GLIBCXX20_CONSTEXPR
2078 tuple(allocator_arg_t __tag, const _Alloc& __a,
2079 const pair<_U1, _U2>& __in)
2080 : _Inherited(__tag, __a, __in.first, __in.second)
2081 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2083 template<typename _Alloc, typename _U1, typename _U2,
2084 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2086 _GLIBCXX20_CONSTEXPR
2087 tuple(allocator_arg_t __tag, const _Alloc& __a,
2088 const pair<_U1, _U2>& __in)
2089 : _Inherited(__tag, __a, __in.first, __in.second)
2090 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2092 template<typename _Alloc, typename _U1, typename _U2,
2093 _ImplicitCtor<true, _U1, _U2> = true>
2094 _GLIBCXX20_CONSTEXPR
2095 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2096 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2097 std::forward<_U2>(__in.second))
2098 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2100 template<typename _Alloc, typename _U1, typename _U2,
2101 _ExplicitCtor<true, _U1, _U2> = false>
2103 _GLIBCXX20_CONSTEXPR
2104 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2105 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2106 std::forward<_U2>(__in.second))
2107 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2109 // Tuple assignment.
2111 _GLIBCXX20_CONSTEXPR
2113 operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
2115 const __nonesuch&> __in)
2116 noexcept(__nothrow_assignable<const _T1&, const _T2&>())
2118 this->_M_assign(__in);
2122 _GLIBCXX20_CONSTEXPR
2124 operator=(__conditional_t<__assignable<_T1, _T2>(),
2127 noexcept(__nothrow_assignable<_T1, _T2>())
2129 this->_M_assign(std::move(__in));
2133 template<typename _U1, typename _U2>
2134 _GLIBCXX20_CONSTEXPR
2135 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2136 operator=(const tuple<_U1, _U2>& __in)
2137 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2139 this->_M_assign(__in);
2143 template<typename _U1, typename _U2>
2144 _GLIBCXX20_CONSTEXPR
2145 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2146 operator=(tuple<_U1, _U2>&& __in)
2147 noexcept(__nothrow_assignable<_U1, _U2>())
2149 this->_M_assign(std::move(__in));
2153 template<typename _U1, typename _U2>
2154 _GLIBCXX20_CONSTEXPR
2155 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2156 operator=(const pair<_U1, _U2>& __in)
2157 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2159 this->_M_head(*this) = __in.first;
2160 this->_M_tail(*this)._M_head(*this) = __in.second;
2164 template<typename _U1, typename _U2>
2165 _GLIBCXX20_CONSTEXPR
2166 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2167 operator=(pair<_U1, _U2>&& __in)
2168 noexcept(__nothrow_assignable<_U1, _U2>())
2170 this->_M_head(*this) = std::forward<_U1>(__in.first);
2171 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
2175 _GLIBCXX20_CONSTEXPR
2178 noexcept(__and_<__is_nothrow_swappable<_T1>,
2179 __is_nothrow_swappable<_T2>>::value)
2180 { _Inherited::_M_swap(__in); }
2182 #endif // concepts && conditional_explicit
2184 /// class tuple_size
2185 template<typename... _Elements>
2186 struct tuple_size<tuple<_Elements...>>
2187 : public integral_constant<size_t, sizeof...(_Elements)> { };
2189 #if __cplusplus >= 201703L
2190 template<typename... _Types>
2191 inline constexpr size_t tuple_size_v<tuple<_Types...>>
2192 = sizeof...(_Types);
2194 template<typename... _Types>
2195 inline constexpr size_t tuple_size_v<const tuple<_Types...>>
2196 = sizeof...(_Types);
2199 /// Trait to get the Ith element type from a tuple.
2200 template<size_t __i, typename... _Types>
2201 struct tuple_element<__i, tuple<_Types...>>
2203 static_assert(__i < sizeof...(_Types), "tuple index must be in range");
2205 using type = typename _Nth_type<__i, _Types...>::type;
2208 template<size_t __i, typename _Head, typename... _Tail>
2210 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2211 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2213 template<size_t __i, typename _Head, typename... _Tail>
2214 constexpr const _Head&
2215 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2216 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2218 // Deleted overload to improve diagnostics for invalid indices
2219 template<size_t __i, typename... _Types>
2220 __enable_if_t<(__i >= sizeof...(_Types))>
2221 __get_helper(const tuple<_Types...>&) = delete;
2223 /// Return a reference to the ith element of a tuple.
2224 template<size_t __i, typename... _Elements>
2225 constexpr __tuple_element_t<__i, tuple<_Elements...>>&
2226 get(tuple<_Elements...>& __t) noexcept
2227 { return std::__get_helper<__i>(__t); }
2229 /// Return a const reference to the ith element of a const tuple.
2230 template<size_t __i, typename... _Elements>
2231 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
2232 get(const tuple<_Elements...>& __t) noexcept
2233 { return std::__get_helper<__i>(__t); }
2235 /// Return an rvalue reference to the ith element of a tuple rvalue.
2236 template<size_t __i, typename... _Elements>
2237 constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
2238 get(tuple<_Elements...>&& __t) noexcept
2240 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2241 return std::forward<__element_type>(std::__get_helper<__i>(__t));
2244 /// Return a const rvalue reference to the ith element of a const tuple rvalue.
2245 template<size_t __i, typename... _Elements>
2246 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
2247 get(const tuple<_Elements...>&& __t) noexcept
2249 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2250 return std::forward<const __element_type>(std::__get_helper<__i>(__t));
2253 /// @cond undocumented
2254 // Deleted overload chosen for invalid indices.
2255 template<size_t __i, typename... _Elements>
2256 constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
2257 get(const tuple<_Elements...>&) = delete;
2260 #ifdef __cpp_lib_tuples_by_type // C++ >= 14
2261 /// Return a reference to the unique element of type _Tp of a tuple.
2262 template <typename _Tp, typename... _Types>
2264 get(tuple<_Types...>& __t) noexcept
2266 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2267 static_assert(__idx < sizeof...(_Types),
2268 "the type T in std::get<T> must occur exactly once in the tuple");
2269 return std::__get_helper<__idx>(__t);
2272 /// Return a reference to the unique element of type _Tp of a tuple rvalue.
2273 template <typename _Tp, typename... _Types>
2275 get(tuple<_Types...>&& __t) noexcept
2277 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2278 static_assert(__idx < sizeof...(_Types),
2279 "the type T in std::get<T> must occur exactly once in the tuple");
2280 return std::forward<_Tp>(std::__get_helper<__idx>(__t));
2283 /// Return a const reference to the unique element of type _Tp of a tuple.
2284 template <typename _Tp, typename... _Types>
2285 constexpr const _Tp&
2286 get(const tuple<_Types...>& __t) noexcept
2288 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2289 static_assert(__idx < sizeof...(_Types),
2290 "the type T in std::get<T> must occur exactly once in the tuple");
2291 return std::__get_helper<__idx>(__t);
2294 /// Return a const reference to the unique element of type _Tp of
2295 /// a const tuple rvalue.
2296 template <typename _Tp, typename... _Types>
2297 constexpr const _Tp&&
2298 get(const tuple<_Types...>&& __t) noexcept
2300 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2301 static_assert(__idx < sizeof...(_Types),
2302 "the type T in std::get<T> must occur exactly once in the tuple");
2303 return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
2307 // This class performs the comparison operations on tuples
2308 template<typename _Tp, typename _Up, size_t __i, size_t __size>
2309 struct __tuple_compare
2311 static constexpr bool
2312 __eq(const _Tp& __t, const _Up& __u)
2314 return bool(std::get<__i>(__t) == std::get<__i>(__u))
2315 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
2318 static constexpr bool
2319 __less(const _Tp& __t, const _Up& __u)
2321 return bool(std::get<__i>(__t) < std::get<__i>(__u))
2322 || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
2323 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
2327 template<typename _Tp, typename _Up, size_t __size>
2328 struct __tuple_compare<_Tp, _Up, __size, __size>
2330 static constexpr bool
2331 __eq(const _Tp&, const _Up&) { return true; }
2333 static constexpr bool
2334 __less(const _Tp&, const _Up&) { return false; }
2337 template<typename... _TElements, typename... _UElements>
2339 operator==(const tuple<_TElements...>& __t,
2340 const tuple<_UElements...>& __u)
2342 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2343 "tuple objects can only be compared if they have equal sizes.");
2344 using __compare = __tuple_compare<tuple<_TElements...>,
2345 tuple<_UElements...>,
2346 0, sizeof...(_TElements)>;
2347 return __compare::__eq(__t, __u);
2350 #if __cpp_lib_three_way_comparison
2351 template<typename _Cat, typename _Tp, typename _Up>
2353 __tuple_cmp(const _Tp&, const _Up&, index_sequence<>)
2354 { return _Cat::equivalent; }
2356 template<typename _Cat, typename _Tp, typename _Up,
2357 size_t _Idx0, size_t... _Idxs>
2359 __tuple_cmp(const _Tp& __t, const _Up& __u,
2360 index_sequence<_Idx0, _Idxs...>)
2363 = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u));
2366 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>());
2369 template<typename... _Tps, typename... _Ups>
2371 common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
2372 operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
2375 = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
2376 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
2379 template<typename... _TElements, typename... _UElements>
2381 operator<(const tuple<_TElements...>& __t,
2382 const tuple<_UElements...>& __u)
2384 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2385 "tuple objects can only be compared if they have equal sizes.");
2386 using __compare = __tuple_compare<tuple<_TElements...>,
2387 tuple<_UElements...>,
2388 0, sizeof...(_TElements)>;
2389 return __compare::__less(__t, __u);
2392 template<typename... _TElements, typename... _UElements>
2394 operator!=(const tuple<_TElements...>& __t,
2395 const tuple<_UElements...>& __u)
2396 { return !(__t == __u); }
2398 template<typename... _TElements, typename... _UElements>
2400 operator>(const tuple<_TElements...>& __t,
2401 const tuple<_UElements...>& __u)
2402 { return __u < __t; }
2404 template<typename... _TElements, typename... _UElements>
2406 operator<=(const tuple<_TElements...>& __t,
2407 const tuple<_UElements...>& __u)
2408 { return !(__u < __t); }
2410 template<typename... _TElements, typename... _UElements>
2412 operator>=(const tuple<_TElements...>& __t,
2413 const tuple<_UElements...>& __u)
2414 { return !(__t < __u); }
2415 #endif // three_way_comparison
2418 /// Create a tuple containing copies of the arguments
2419 template<typename... _Elements>
2420 constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
2421 make_tuple(_Elements&&... __args)
2423 typedef tuple<typename __decay_and_strip<_Elements>::__type...>
2425 return __result_type(std::forward<_Elements>(__args)...);
2428 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2429 // 2275. Why is forward_as_tuple not constexpr?
2430 /// Create a tuple of lvalue or rvalue references to the arguments
2431 template<typename... _Elements>
2432 constexpr tuple<_Elements&&...>
2433 forward_as_tuple(_Elements&&... __args) noexcept
2434 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2436 // Declarations of std::array and its std::get overloads, so that
2437 // std::tuple_cat can use them if <tuple> is included before <array>.
2439 template<typename _Tp, size_t _Nm> struct array;
2441 template<size_t _Int, typename _Tp, size_t _Nm>
2443 get(array<_Tp, _Nm>&) noexcept;
2445 template<size_t _Int, typename _Tp, size_t _Nm>
2447 get(array<_Tp, _Nm>&&) noexcept;
2449 template<size_t _Int, typename _Tp, size_t _Nm>
2450 constexpr const _Tp&
2451 get(const array<_Tp, _Nm>&) noexcept;
2453 template<size_t _Int, typename _Tp, size_t _Nm>
2454 constexpr const _Tp&&
2455 get(const array<_Tp, _Nm>&&) noexcept;
2457 /// @cond undocumented
2458 template<size_t, typename, typename, size_t>
2459 struct __make_tuple_impl;
2461 template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
2462 struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
2463 : __make_tuple_impl<_Idx + 1,
2464 tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
2468 template<size_t _Nm, typename _Tuple, typename... _Tp>
2469 struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
2471 typedef tuple<_Tp...> __type;
2474 template<typename _Tuple>
2475 struct __do_make_tuple
2476 : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
2479 // Returns the std::tuple equivalent of a tuple-like type.
2480 template<typename _Tuple>
2482 : public __do_make_tuple<__remove_cvref_t<_Tuple>>
2485 // Combines several std::tuple's into a single one.
2486 template<typename...>
2487 struct __combine_tuples;
2490 struct __combine_tuples<>
2492 typedef tuple<> __type;
2495 template<typename... _Ts>
2496 struct __combine_tuples<tuple<_Ts...>>
2498 typedef tuple<_Ts...> __type;
2501 template<typename... _T1s, typename... _T2s, typename... _Rem>
2502 struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
2504 typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
2505 _Rem...>::__type __type;
2508 // Computes the result type of tuple_cat given a set of tuple-like types.
2509 template<typename... _Tpls>
2510 struct __tuple_cat_result
2512 typedef typename __combine_tuples
2513 <typename __make_tuple<_Tpls>::__type...>::__type __type;
2516 // Helper to determine the index set for the first tuple-like
2517 // type of a given set.
2518 template<typename...>
2519 struct __make_1st_indices;
2522 struct __make_1st_indices<>
2524 typedef _Index_tuple<> __type;
2527 template<typename _Tp, typename... _Tpls>
2528 struct __make_1st_indices<_Tp, _Tpls...>
2530 typedef typename _Build_index_tuple<tuple_size<
2531 typename remove_reference<_Tp>::type>::value>::__type __type;
2534 // Performs the actual concatenation by step-wise expanding tuple-like
2535 // objects into the elements, which are finally forwarded into the
2537 template<typename _Ret, typename _Indices, typename... _Tpls>
2538 struct __tuple_concater;
2540 template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2541 struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2543 template<typename... _Us>
2544 static constexpr _Ret
2545 _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2547 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2548 typedef __tuple_concater<_Ret, __idx, _Tpls...> __next;
2549 return __next::_S_do(std::forward<_Tpls>(__tps)...,
2550 std::forward<_Us>(__us)...,
2551 std::get<_Is>(std::forward<_Tp>(__tp))...);
2555 template<typename _Ret>
2556 struct __tuple_concater<_Ret, _Index_tuple<>>
2558 template<typename... _Us>
2559 static constexpr _Ret
2560 _S_do(_Us&&... __us)
2562 return _Ret(std::forward<_Us>(__us)...);
2566 template<typename... _Tps>
2567 struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2571 /// Create a `tuple` containing all elements from multiple tuple-like objects
2572 template<typename... _Tpls, typename = typename
2573 enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2575 tuple_cat(_Tpls&&... __tpls)
2576 -> typename __tuple_cat_result<_Tpls...>::__type
2578 typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2579 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2580 typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2581 return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2584 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2585 // 2301. Why is tie not constexpr?
2586 /// Return a tuple of lvalue references bound to the arguments
2587 template<typename... _Elements>
2588 constexpr tuple<_Elements&...>
2589 tie(_Elements&... __args) noexcept
2590 { return tuple<_Elements&...>(__args...); }
2592 /// Exchange the values of two tuples
2593 template<typename... _Elements>
2594 _GLIBCXX20_CONSTEXPR
2596 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2597 // Constrained free swap overload, see p0185r1
2598 typename enable_if<__and_<__is_swappable<_Elements>...>::value
2603 swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
2604 noexcept(noexcept(__x.swap(__y)))
2607 #if __cpp_lib_ranges_zip // >= C++23
2608 template<typename... _Elements>
2609 requires (is_swappable_v<const _Elements> && ...)
2611 swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2612 noexcept(noexcept(__x.swap(__y)))
2616 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2617 /// Exchange the values of two const tuples (if const elements can be swapped)
2618 template<typename... _Elements>
2619 _GLIBCXX20_CONSTEXPR
2620 typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2621 swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2624 // A class (and instance) which can be used in 'tie' when an element
2625 // of a tuple is not required.
2626 // _GLIBCXX14_CONSTEXPR
2627 // 2933. PR for LWG 2773 could be clearer
2628 struct _Swallow_assign
2631 _GLIBCXX14_CONSTEXPR const _Swallow_assign&
2632 operator=(const _Tp&) const
2636 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2637 // 2773. Making std::ignore constexpr
2638 /** Used with `std::tie` to ignore an element of a tuple
2640 * When using `std::tie` to assign the elements of a tuple to variables,
2641 * unwanted elements can be ignored by using `std::ignore`. For example:
2645 * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3);
2648 * This assignment will perform `x=1; std::ignore=2; y=3;` which results
2649 * in the second element being ignored.
2653 _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{};
2655 /// Partial specialization for tuples
2656 template<typename... _Types, typename _Alloc>
2657 struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2659 // See stl_pair.h...
2660 /** "piecewise construction" using a tuple of arguments for each member.
2662 * @param __first Arguments for the first member of the pair.
2663 * @param __second Arguments for the second member of the pair.
2665 * The elements of each tuple will be used as the constructor arguments
2666 * for the data members of the pair.
2668 template<class _T1, class _T2>
2669 template<typename... _Args1, typename... _Args2>
2670 _GLIBCXX20_CONSTEXPR
2673 pair(piecewise_construct_t,
2674 tuple<_Args1...> __first, tuple<_Args2...> __second)
2675 : pair(__first, __second,
2676 typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2677 typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2680 template<class _T1, class _T2>
2681 template<typename... _Args1, size_t... _Indexes1,
2682 typename... _Args2, size_t... _Indexes2>
2683 _GLIBCXX20_CONSTEXPR inline
2685 pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2686 _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2687 : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2688 second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2691 #if defined(__cpp_lib_apply) || defined(__cpp_lib_make_from_tuple) // C++ >= 17
2692 // Unpack a std::tuple into a type trait and use its value.
2693 // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2694 // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2695 // Otherwise the result is false (because we don't know if std::get throws).
2696 template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2697 inline constexpr bool __unpack_std_tuple = false;
2699 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2700 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2701 = _Trait<_Tp, _Up...>::value;
2703 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2704 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2705 = _Trait<_Tp, _Up&...>::value;
2707 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2708 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2709 = _Trait<_Tp, const _Up...>::value;
2711 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2712 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2713 = _Trait<_Tp, const _Up&...>::value;
2716 #ifdef __cpp_lib_apply // C++ >= 17
2717 template <typename _Fn, typename _Tuple, size_t... _Idx>
2718 constexpr decltype(auto)
2719 __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2721 return std::__invoke(std::forward<_Fn>(__f),
2722 std::get<_Idx>(std::forward<_Tuple>(__t))...);
2725 template <typename _Fn, typename _Tuple>
2726 constexpr decltype(auto)
2727 apply(_Fn&& __f, _Tuple&& __t)
2728 noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2731 = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2732 return std::__apply_impl(std::forward<_Fn>(__f),
2733 std::forward<_Tuple>(__t),
2738 #ifdef __cpp_lib_make_from_tuple // C++ >= 17
2739 template <typename _Tp, typename _Tuple, size_t... _Idx>
2741 __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
2742 { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
2744 template <typename _Tp, typename _Tuple>
2746 make_from_tuple(_Tuple&& __t)
2747 noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
2749 constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
2750 #if __has_builtin(__reference_constructs_from_temporary)
2751 if constexpr (__n == 1)
2753 using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
2754 static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
2757 return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
2758 make_index_sequence<__n>{});
2762 #if __cpp_lib_ranges_zip // >= C++23
2763 template<typename... _TTypes, typename... _UTypes,
2764 template<typename> class _TQual, template<typename> class _UQual>
2765 requires requires { typename tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; }
2766 struct basic_common_reference<tuple<_TTypes...>, tuple<_UTypes...>, _TQual, _UQual>
2767 { using type = tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; };
2769 template<typename... _TTypes, typename... _UTypes>
2770 requires requires { typename tuple<common_type_t<_TTypes, _UTypes>...>; }
2771 struct common_type<tuple<_TTypes...>, tuple<_UTypes...>>
2772 { using type = tuple<common_type_t<_TTypes, _UTypes>...>; };
2777 #undef __glibcxx_no_dangling_refs
2779 _GLIBCXX_END_NAMESPACE_VERSION
2784 #endif // _GLIBCXX_TUPLE