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 #define __glibcxx_want_tuple_like
54 #define __glibcxx_want_constrained_equality
55 #include <bits/version.h>
57 namespace std _GLIBCXX_VISIBILITY(default)
59 _GLIBCXX_BEGIN_NAMESPACE_VERSION
62 * @addtogroup utilities
66 template<typename... _Elements>
69 template<typename _Tp>
70 struct __is_empty_non_tuple : is_empty<_Tp> { };
72 // Using EBO for elements that are tuples causes ambiguous base errors.
73 template<typename _El0, typename... _El>
74 struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { };
76 // Use the Empty Base-class Optimization for empty, non-final types.
77 template<typename _Tp>
78 using __empty_not_final
79 = __conditional_t<__is_final(_Tp), false_type,
80 __is_empty_non_tuple<_Tp>>;
82 template<size_t _Idx, typename _Head,
83 bool = __empty_not_final<_Head>::value>
86 #if __has_cpp_attribute(__no_unique_address__)
87 template<size_t _Idx, typename _Head>
88 struct _Head_base<_Idx, _Head, true>
90 constexpr _Head_base()
93 constexpr _Head_base(const _Head& __h)
94 : _M_head_impl(__h) { }
96 constexpr _Head_base(const _Head_base&) = default;
97 constexpr _Head_base(_Head_base&&) = default;
99 template<typename _UHead>
100 constexpr _Head_base(_UHead&& __h)
101 : _M_head_impl(std::forward<_UHead>(__h)) { }
104 _Head_base(allocator_arg_t, __uses_alloc0)
107 template<typename _Alloc>
109 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
110 : _M_head_impl(allocator_arg, *__a._M_a) { }
112 template<typename _Alloc>
114 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
115 : _M_head_impl(*__a._M_a) { }
117 template<typename _UHead>
119 _Head_base(__uses_alloc0, _UHead&& __uhead)
120 : _M_head_impl(std::forward<_UHead>(__uhead)) { }
122 template<typename _Alloc, typename _UHead>
124 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
125 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
128 template<typename _Alloc, typename _UHead>
130 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
131 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
133 static constexpr _Head&
134 _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
136 static constexpr const _Head&
137 _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
139 [[__no_unique_address__]] _Head _M_head_impl;
142 template<size_t _Idx, typename _Head>
143 struct _Head_base<_Idx, _Head, true>
146 constexpr _Head_base()
149 constexpr _Head_base(const _Head& __h)
152 constexpr _Head_base(const _Head_base&) = default;
153 constexpr _Head_base(_Head_base&&) = default;
155 template<typename _UHead>
156 constexpr _Head_base(_UHead&& __h)
157 : _Head(std::forward<_UHead>(__h)) { }
160 _Head_base(allocator_arg_t, __uses_alloc0)
163 template<typename _Alloc>
165 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
166 : _Head(allocator_arg, *__a._M_a) { }
168 template<typename _Alloc>
170 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
171 : _Head(*__a._M_a) { }
173 template<typename _UHead>
175 _Head_base(__uses_alloc0, _UHead&& __uhead)
176 : _Head(std::forward<_UHead>(__uhead)) { }
178 template<typename _Alloc, typename _UHead>
180 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
181 : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
183 template<typename _Alloc, typename _UHead>
185 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
186 : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
188 static constexpr _Head&
189 _M_head(_Head_base& __b) noexcept { return __b; }
191 static constexpr const _Head&
192 _M_head(const _Head_base& __b) noexcept { return __b; }
196 template<size_t _Idx, typename _Head>
197 struct _Head_base<_Idx, _Head, false>
199 constexpr _Head_base()
202 constexpr _Head_base(const _Head& __h)
203 : _M_head_impl(__h) { }
205 constexpr _Head_base(const _Head_base&) = default;
206 constexpr _Head_base(_Head_base&&) = default;
208 template<typename _UHead>
209 constexpr _Head_base(_UHead&& __h)
210 : _M_head_impl(std::forward<_UHead>(__h)) { }
213 _Head_base(allocator_arg_t, __uses_alloc0)
216 template<typename _Alloc>
218 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
219 : _M_head_impl(allocator_arg, *__a._M_a) { }
221 template<typename _Alloc>
223 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
224 : _M_head_impl(*__a._M_a) { }
226 template<typename _UHead>
228 _Head_base(__uses_alloc0, _UHead&& __uhead)
229 : _M_head_impl(std::forward<_UHead>(__uhead)) { }
231 template<typename _Alloc, typename _UHead>
233 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
234 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
237 template<typename _Alloc, typename _UHead>
239 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
240 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
242 static constexpr _Head&
243 _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
245 static constexpr const _Head&
246 _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
251 #if __cpp_lib_tuple_like // >= C++23
252 struct __tuple_like_tag_t { explicit __tuple_like_tag_t() = default; };
254 // This forward declaration is used by the operator<=> overload for
256 template<typename _Cat, typename _Tp, typename _Up, typename _IndexSeq>
258 __tuple_cmp(const _Tp& __t, const _Up& __u, _IndexSeq);
262 * Contains the actual implementation of the @c tuple template, stored
263 * as a recursive inheritance hierarchy from the first element (most
264 * derived class) to the last (least derived class). The @c Idx
265 * parameter gives the 0-based index of the element stored at this
266 * point in the hierarchy; we use it to implement a constant-time
269 template<size_t _Idx, typename... _Elements>
273 * Recursive tuple implementation. Here we store the @c Head element
274 * and derive from a @c Tuple_impl containing the remaining elements
275 * (which contains the @c Tail).
277 template<size_t _Idx, typename _Head, typename... _Tail>
278 struct _Tuple_impl<_Idx, _Head, _Tail...>
279 : public _Tuple_impl<_Idx + 1, _Tail...>,
280 private _Head_base<_Idx, _Head>
282 template<size_t, typename...> friend struct _Tuple_impl;
284 typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
285 typedef _Head_base<_Idx, _Head> _Base;
287 static constexpr _Head&
288 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
290 static constexpr const _Head&
291 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
293 static constexpr _Inherited&
294 _M_tail(_Tuple_impl& __t) noexcept { return __t; }
296 static constexpr const _Inherited&
297 _M_tail(const _Tuple_impl& __t) noexcept { return __t; }
299 constexpr _Tuple_impl()
300 : _Inherited(), _Base() { }
303 _Tuple_impl(const _Head& __head, const _Tail&... __tail)
304 : _Inherited(__tail...), _Base(__head)
307 template<typename _UHead, typename... _UTail,
308 typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
310 _Tuple_impl(_UHead&& __head, _UTail&&... __tail)
311 : _Inherited(std::forward<_UTail>(__tail)...),
312 _Base(std::forward<_UHead>(__head))
315 constexpr _Tuple_impl(const _Tuple_impl&) = default;
317 // _GLIBCXX_RESOLVE_LIB_DEFECTS
318 // 2729. Missing SFINAE on std::pair::operator=
319 _Tuple_impl& operator=(const _Tuple_impl&) = delete;
321 _Tuple_impl(_Tuple_impl&&) = default;
323 template<typename... _UElements>
325 _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
326 : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
327 _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
330 template<typename _UHead, typename... _UTails>
332 _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
333 : _Inherited(std::move
334 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
335 _Base(std::forward<_UHead>
336 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
339 #if __cpp_lib_ranges_zip // >= C++23
340 template<typename... _UElements>
342 _Tuple_impl(_Tuple_impl<_Idx, _UElements...>& __in)
343 : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
344 _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
347 template<typename _UHead, typename... _UTails>
349 _Tuple_impl(const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
350 : _Inherited(std::move
351 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
352 _Base(std::forward<const _UHead>
353 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
357 #if __cpp_lib_tuple_like // >= C++23
358 template<typename _UTuple, size_t... _Is>
360 _Tuple_impl(__tuple_like_tag_t, _UTuple&& __u, index_sequence<_Is...>)
361 : _Tuple_impl(std::get<_Is>(std::forward<_UTuple>(__u))...)
365 template<typename _Alloc>
367 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
368 : _Inherited(__tag, __a),
369 _Base(__tag, __use_alloc<_Head>(__a))
372 template<typename _Alloc>
374 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
375 const _Head& __head, const _Tail&... __tail)
376 : _Inherited(__tag, __a, __tail...),
377 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head)
380 template<typename _Alloc, typename _UHead, typename... _UTail,
381 typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
383 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
384 _UHead&& __head, _UTail&&... __tail)
385 : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
386 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
387 std::forward<_UHead>(__head))
390 template<typename _Alloc>
392 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
393 const _Tuple_impl& __in)
394 : _Inherited(__tag, __a, _M_tail(__in)),
395 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in))
398 template<typename _Alloc>
400 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
402 : _Inherited(__tag, __a, std::move(_M_tail(__in))),
403 _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
404 std::forward<_Head>(_M_head(__in)))
407 template<typename _Alloc, typename _UHead, typename... _UTails>
409 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
410 const _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
411 : _Inherited(__tag, __a,
412 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
413 _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
414 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
417 template<typename _Alloc, typename _UHead, typename... _UTails>
419 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
420 _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
421 : _Inherited(__tag, __a, std::move
422 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
423 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
425 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
428 #if __cpp_lib_ranges_zip // >= C++23
429 template<typename _Alloc, typename _UHead, typename... _UTails>
431 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
432 _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
433 : _Inherited(__tag, __a,
434 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
435 _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
436 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
439 template<typename _Alloc, typename _UHead, typename... _UTails>
441 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
442 const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
443 : _Inherited(__tag, __a, std::move
444 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
445 _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
446 std::forward<const _UHead>
447 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
451 #if __cpp_lib_tuple_like // >= C++23
452 template<typename _Alloc, typename _UTuple, size_t... _Is>
454 _Tuple_impl(__tuple_like_tag_t, allocator_arg_t __tag, const _Alloc& __a,
455 _UTuple&& __u, index_sequence<_Is...>)
456 : _Tuple_impl(__tag, __a, std::get<_Is>(std::forward<_UTuple>(__u))...)
460 template<typename... _UElements>
463 _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in)
465 _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
466 _M_tail(*this)._M_assign(
467 _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
470 template<typename _UHead, typename... _UTails>
473 _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
475 _M_head(*this) = std::forward<_UHead>
476 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
477 _M_tail(*this)._M_assign(
478 std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
481 #if __cpp_lib_ranges_zip // >= C++23
482 template<typename... _UElements>
484 _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) const
486 _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
487 _M_tail(*this)._M_assign(
488 _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
491 template<typename _UHead, typename... _UTails>
493 _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) const
495 _M_head(*this) = std::forward<_UHead>
496 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
497 _M_tail(*this)._M_assign(
498 std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
502 #if __cpp_lib_tuple_like // >= C++23
503 template<typename _UTuple>
505 _M_assign(__tuple_like_tag_t __tag, _UTuple&& __u)
507 _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u));
508 _M_tail(*this)._M_assign(__tag, std::forward<_UTuple>(__u));
511 template<typename _UTuple>
513 _M_assign(__tuple_like_tag_t __tag, _UTuple&& __u) const
515 _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u));
516 _M_tail(*this)._M_assign(__tag, std::forward<_UTuple>(__u));
523 _M_swap(_Tuple_impl& __in)
526 swap(_M_head(*this), _M_head(__in));
527 _Inherited::_M_swap(_M_tail(__in));
530 #if __cpp_lib_ranges_zip // >= C++23
532 _M_swap(const _Tuple_impl& __in) const
535 swap(_M_head(*this), _M_head(__in));
536 _Inherited::_M_swap(_M_tail(__in));
541 // Basis case of inheritance recursion.
542 template<size_t _Idx, typename _Head>
543 struct _Tuple_impl<_Idx, _Head>
544 : private _Head_base<_Idx, _Head>
546 template<size_t, typename...> friend struct _Tuple_impl;
548 typedef _Head_base<_Idx, _Head> _Base;
550 static constexpr _Head&
551 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
553 static constexpr const _Head&
554 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
561 _Tuple_impl(const _Head& __head)
565 template<typename _UHead>
567 _Tuple_impl(_UHead&& __head)
568 : _Base(std::forward<_UHead>(__head))
571 constexpr _Tuple_impl(const _Tuple_impl&) = default;
573 // _GLIBCXX_RESOLVE_LIB_DEFECTS
574 // 2729. Missing SFINAE on std::pair::operator=
575 _Tuple_impl& operator=(const _Tuple_impl&) = delete;
577 #if _GLIBCXX_INLINE_VERSION
578 _Tuple_impl(_Tuple_impl&&) = default;
581 _Tuple_impl(_Tuple_impl&& __in)
582 noexcept(is_nothrow_move_constructible<_Head>::value)
583 : _Base(static_cast<_Base&&>(__in))
587 template<typename _UHead>
589 _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in)
590 : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
593 template<typename _UHead>
595 _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in)
596 : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
599 #if __cpp_lib_ranges_zip // >= C++23
600 template<typename _UHead>
602 _Tuple_impl(_Tuple_impl<_Idx, _UHead>& __in)
603 : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
606 template<typename _UHead>
608 _Tuple_impl(const _Tuple_impl<_Idx, _UHead>&& __in)
609 : _Base(std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
613 #if __cpp_lib_tuple_like // >= C++23
614 template<typename _UTuple>
616 _Tuple_impl(__tuple_like_tag_t, _UTuple&& __u, index_sequence<0>)
617 : _Tuple_impl(std::get<0>(std::forward<_UTuple>(__u)))
621 template<typename _Alloc>
623 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
624 : _Base(__tag, __use_alloc<_Head>(__a))
627 template<typename _Alloc>
629 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
631 : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), __head)
634 template<typename _Alloc, typename _UHead>
636 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
638 : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
639 std::forward<_UHead>(__head))
642 template<typename _Alloc>
644 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
645 const _Tuple_impl& __in)
646 : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), _M_head(__in))
649 template<typename _Alloc>
651 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
653 : _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
654 std::forward<_Head>(_M_head(__in)))
657 template<typename _Alloc, typename _UHead>
659 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
660 const _Tuple_impl<_Idx, _UHead>& __in)
661 : _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
662 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
665 template<typename _Alloc, typename _UHead>
667 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
668 _Tuple_impl<_Idx, _UHead>&& __in)
669 : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
670 std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
673 #if __cpp_lib_ranges_zip // >= C++23
674 template<typename _Alloc, typename _UHead>
676 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
677 _Tuple_impl<_Idx, _UHead>& __in)
678 : _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
679 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
682 template<typename _Alloc, typename _UHead>
684 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
685 const _Tuple_impl<_Idx, _UHead>&& __in)
686 : _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
687 std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
691 #if __cpp_lib_tuple_like // >= C++23
692 template<typename _Alloc, typename _UTuple>
694 _Tuple_impl(__tuple_like_tag_t, allocator_arg_t __tag, const _Alloc& __a,
695 _UTuple&& __u, index_sequence<0>)
696 : _Tuple_impl(__tag, __a, std::get<0>(std::forward<_UTuple>(__u)))
700 template<typename _UHead>
703 _M_assign(const _Tuple_impl<_Idx, _UHead>& __in)
705 _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
708 template<typename _UHead>
711 _M_assign(_Tuple_impl<_Idx, _UHead>&& __in)
714 = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
717 #if __cpp_lib_ranges_zip // >= C++23
718 template<typename _UHead>
720 _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) const
722 _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
725 template<typename _UHead>
727 _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) const
730 = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
734 #if __cpp_lib_tuple_like // >= C++23
735 template<typename _UTuple>
737 _M_assign(__tuple_like_tag_t, _UTuple&& __u)
738 { _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); }
740 template<typename _UTuple>
742 _M_assign(__tuple_like_tag_t, _UTuple&& __u) const
743 { _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); }
749 _M_swap(_Tuple_impl& __in)
752 swap(_M_head(*this), _M_head(__in));
755 #if __cpp_lib_ranges_zip // >= C++23
757 _M_swap(const _Tuple_impl& __in) const
760 swap(_M_head(*this), _M_head(__in));
765 // Concept utility functions, reused in conditionally-explicit
767 template<bool, typename... _Types>
768 struct _TupleConstraints
770 template<typename... _UTypes>
771 using __constructible = __and_<is_constructible<_Types, _UTypes>...>;
773 template<typename... _UTypes>
774 using __convertible = __and_<is_convertible<_UTypes, _Types>...>;
776 // Constraint for a non-explicit constructor.
777 // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
778 // and every Ui is implicitly convertible to Ti.
779 template<typename... _UTypes>
780 static constexpr bool __is_implicitly_constructible()
782 return __and_<__constructible<_UTypes...>,
783 __convertible<_UTypes...>
787 // Constraint for a non-explicit constructor.
788 // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
789 // but not every Ui is implicitly convertible to Ti.
790 template<typename... _UTypes>
791 static constexpr bool __is_explicitly_constructible()
793 return __and_<__constructible<_UTypes...>,
794 __not_<__convertible<_UTypes...>>
798 static constexpr bool __is_implicitly_default_constructible()
800 return __and_<std::__is_implicitly_default_constructible<_Types>...
804 static constexpr bool __is_explicitly_default_constructible()
806 return __and_<is_default_constructible<_Types>...,
808 std::__is_implicitly_default_constructible<_Types>...>
813 // Partial specialization used when a required precondition isn't met,
814 // e.g. when sizeof...(_Types) != sizeof...(_UTypes).
815 template<typename... _Types>
816 struct _TupleConstraints<false, _Types...>
818 template<typename... _UTypes>
819 static constexpr bool __is_implicitly_constructible()
822 template<typename... _UTypes>
823 static constexpr bool __is_explicitly_constructible()
827 /// Primary class template, tuple
828 template<typename... _Elements>
829 class tuple : public _Tuple_impl<0, _Elements...>
831 using _Inherited = _Tuple_impl<0, _Elements...>;
833 #if __cpp_concepts && __cpp_consteval && __cpp_conditional_explicit // >= C++20
834 template<typename... _UTypes>
835 static consteval bool
838 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
839 return __and_v<is_constructible<_Elements, _UTypes>...>;
844 template<typename... _UTypes>
845 static consteval bool
846 __nothrow_constructible()
848 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
849 return __and_v<is_nothrow_constructible<_Elements, _UTypes>...>;
854 template<typename... _UTypes>
855 static consteval bool
858 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
859 return __and_v<is_convertible<_UTypes, _Elements>...>;
864 // _GLIBCXX_RESOLVE_LIB_DEFECTS
865 // 3121. tuple constructor constraints for UTypes&&... overloads
866 template<typename... _UTypes>
867 static consteval bool
868 __disambiguating_constraint()
870 if constexpr (sizeof...(_Elements) != sizeof...(_UTypes))
872 else if constexpr (sizeof...(_Elements) == 1)
874 using _U0 = typename _Nth_type<0, _UTypes...>::type;
875 return !is_same_v<remove_cvref_t<_U0>, tuple>;
877 else if constexpr (sizeof...(_Elements) < 4)
879 using _U0 = typename _Nth_type<0, _UTypes...>::type;
880 if constexpr (!is_same_v<remove_cvref_t<_U0>, allocator_arg_t>)
884 using _T0 = typename _Nth_type<0, _Elements...>::type;
885 return is_same_v<remove_cvref_t<_T0>, allocator_arg_t>;
891 // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
892 // and the single element in Types can be initialized from TUPLE,
893 // or is the same type as tuple_element_t<0, TUPLE>.
894 template<typename _Tuple>
895 static consteval bool
898 if constexpr (sizeof...(_Elements) != 1)
900 else if constexpr (is_same_v<remove_cvref_t<_Tuple>, tuple>)
901 return true; // Should use a copy/move constructor instead.
904 using _Tp = typename _Nth_type<0, _Elements...>::type;
905 if constexpr (is_convertible_v<_Tuple, _Tp>)
907 else if constexpr (is_constructible_v<_Tp, _Tuple>)
913 template<typename... _Up>
914 static consteval bool
917 #if __has_builtin(__reference_constructs_from_temporary)
918 return (__reference_constructs_from_temporary(_Elements, _Up&&)
925 #if __cpp_lib_tuple_like // >= C++23
926 // _GLIBCXX_RESOLVE_LIB_DEFECTS
927 // 4045. tuple can create dangling references from tuple-like
928 template<typename _UTuple>
929 static consteval bool
930 __dangles_from_tuple_like()
932 return []<size_t... _Is>(index_sequence<_Is...>) {
933 return __dangles<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
934 }(index_sequence_for<_Elements...>{});
937 template<typename _UTuple>
938 static consteval bool
939 __constructible_from_tuple_like()
941 return []<size_t... _Is>(index_sequence<_Is...>) {
942 return __constructible<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
943 }(index_sequence_for<_Elements...>{});
946 template<typename _UTuple>
947 static consteval bool
948 __convertible_from_tuple_like()
950 return []<size_t... _Is>(index_sequence<_Is...>) {
951 return __convertible<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
952 }(index_sequence_for<_Elements...>{});
958 explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
960 noexcept((is_nothrow_default_constructible_v<_Elements> && ...))
961 requires (is_default_constructible_v<_Elements> && ...)
965 constexpr explicit(!__convertible<const _Elements&...>())
966 tuple(const _Elements&... __elements)
967 noexcept(__nothrow_constructible<const _Elements&...>())
968 requires (__constructible<const _Elements&...>())
969 : _Inherited(__elements...)
972 template<typename... _UTypes>
973 requires (__disambiguating_constraint<_UTypes...>())
974 && (__constructible<_UTypes...>())
975 && (!__dangles<_UTypes...>())
976 constexpr explicit(!__convertible<_UTypes...>())
977 tuple(_UTypes&&... __u)
978 noexcept(__nothrow_constructible<_UTypes...>())
979 : _Inherited(std::forward<_UTypes>(__u)...)
982 template<typename... _UTypes>
983 requires (__disambiguating_constraint<_UTypes...>())
984 && (__constructible<_UTypes...>())
985 && (__dangles<_UTypes...>())
986 tuple(_UTypes&&...) = delete;
988 constexpr tuple(const tuple&) = default;
990 constexpr tuple(tuple&&) = default;
992 template<typename... _UTypes>
993 requires (__constructible<const _UTypes&...>())
994 && (!__use_other_ctor<const tuple<_UTypes...>&>())
995 && (!__dangles<const _UTypes&...>())
996 constexpr explicit(!__convertible<const _UTypes&...>())
997 tuple(const tuple<_UTypes...>& __u)
998 noexcept(__nothrow_constructible<const _UTypes&...>())
999 : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1002 template<typename... _UTypes>
1003 requires (__constructible<const _UTypes&...>())
1004 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1005 && (__dangles<const _UTypes&...>())
1006 tuple(const tuple<_UTypes...>&) = delete;
1008 template<typename... _UTypes>
1009 requires (__constructible<_UTypes...>())
1010 && (!__use_other_ctor<tuple<_UTypes...>>())
1011 && (!__dangles<_UTypes...>())
1012 constexpr explicit(!__convertible<_UTypes...>())
1013 tuple(tuple<_UTypes...>&& __u)
1014 noexcept(__nothrow_constructible<_UTypes...>())
1015 : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1018 template<typename... _UTypes>
1019 requires (__constructible<_UTypes...>())
1020 && (!__use_other_ctor<tuple<_UTypes...>>())
1021 && (__dangles<_UTypes...>())
1022 tuple(tuple<_UTypes...>&&) = delete;
1024 #if __cpp_lib_ranges_zip // >= C++23
1025 template<typename... _UTypes>
1026 requires (__constructible<_UTypes&...>())
1027 && (!__use_other_ctor<tuple<_UTypes...>&>())
1028 && (!__dangles<_UTypes&...>())
1029 constexpr explicit(!__convertible<_UTypes&...>())
1030 tuple(tuple<_UTypes...>& __u)
1031 noexcept(__nothrow_constructible<_UTypes&...>())
1032 : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1035 template<typename... _UTypes>
1036 requires (__constructible<_UTypes&...>())
1037 && (!__use_other_ctor<tuple<_UTypes...>&>())
1038 && (__dangles<_UTypes&...>())
1039 tuple(tuple<_UTypes...>&) = delete;
1041 template<typename... _UTypes>
1042 requires (__constructible<const _UTypes...>())
1043 && (!__use_other_ctor<const tuple<_UTypes...>>())
1044 && (!__dangles<const _UTypes...>())
1045 constexpr explicit(!__convertible<const _UTypes...>())
1046 tuple(const tuple<_UTypes...>&& __u)
1047 noexcept(__nothrow_constructible<const _UTypes...>())
1048 : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1051 template<typename... _UTypes>
1052 requires (__constructible<const _UTypes...>())
1053 && (!__use_other_ctor<const tuple<_UTypes...>>())
1054 && (__dangles<const _UTypes...>())
1055 tuple(const tuple<_UTypes...>&&) = delete;
1058 template<typename _U1, typename _U2>
1059 requires (sizeof...(_Elements) == 2)
1060 && (__constructible<const _U1&, const _U2&>())
1061 && (!__dangles<const _U1&, const _U2&>())
1062 constexpr explicit(!__convertible<const _U1&, const _U2&>())
1063 tuple(const pair<_U1, _U2>& __u)
1064 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1065 : _Inherited(__u.first, __u.second)
1068 template<typename _U1, typename _U2>
1069 requires (sizeof...(_Elements) == 2)
1070 && (__constructible<const _U1&, const _U2&>())
1071 && (__dangles<const _U1&, const _U2&>())
1072 tuple(const pair<_U1, _U2>&) = delete;
1074 template<typename _U1, typename _U2>
1075 requires (sizeof...(_Elements) == 2)
1076 && (__constructible<_U1, _U2>())
1077 && (!__dangles<_U1, _U2>())
1078 constexpr explicit(!__convertible<_U1, _U2>())
1079 tuple(pair<_U1, _U2>&& __u)
1080 noexcept(__nothrow_constructible<_U1, _U2>())
1081 : _Inherited(std::forward<_U1>(__u.first),
1082 std::forward<_U2>(__u.second))
1085 template<typename _U1, typename _U2>
1086 requires (sizeof...(_Elements) == 2)
1087 && (__constructible<_U1, _U2>())
1088 && (__dangles<_U1, _U2>())
1089 tuple(pair<_U1, _U2>&&) = delete;
1091 #if __cpp_lib_ranges_zip // >= C++23
1092 template<typename _U1, typename _U2>
1093 requires (sizeof...(_Elements) == 2)
1094 && (__constructible<_U1&, _U2&>())
1095 && (!__dangles<_U1&, _U2&>())
1096 constexpr explicit(!__convertible<_U1&, _U2&>())
1097 tuple(pair<_U1, _U2>& __u)
1098 noexcept(__nothrow_constructible<_U1&, _U2&>())
1099 : _Inherited(__u.first, __u.second)
1102 template<typename _U1, typename _U2>
1103 requires (sizeof...(_Elements) == 2)
1104 && (__constructible<_U1&, _U2&>())
1105 && (__dangles<_U1&, _U2&>())
1106 tuple(pair<_U1, _U2>&) = delete;
1108 template<typename _U1, typename _U2>
1109 requires (sizeof...(_Elements) == 2)
1110 && (__constructible<const _U1, const _U2>())
1111 && (!__dangles<const _U1, const _U2>())
1112 constexpr explicit(!__convertible<const _U1, const _U2>())
1113 tuple(const pair<_U1, _U2>&& __u)
1114 noexcept(__nothrow_constructible<const _U1, const _U2>())
1115 : _Inherited(std::forward<const _U1>(__u.first),
1116 std::forward<const _U2>(__u.second))
1119 template<typename _U1, typename _U2>
1120 requires (sizeof...(_Elements) == 2)
1121 && (__constructible<const _U1, const _U2>())
1122 && (__dangles<const _U1, const _U2>())
1123 tuple(const pair<_U1, _U2>&&) = delete;
1126 #if __cpp_lib_tuple_like // >= C++23
1127 template<__eligible_tuple_like<tuple> _UTuple>
1128 requires (__constructible_from_tuple_like<_UTuple>())
1129 && (!__use_other_ctor<_UTuple>())
1130 && (!__dangles_from_tuple_like<_UTuple>())
1131 constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
1132 tuple(_UTuple&& __u)
1133 : _Inherited(__tuple_like_tag_t{},
1134 std::forward<_UTuple>(__u),
1135 index_sequence_for<_Elements...>{})
1138 template<__eligible_tuple_like<tuple> _UTuple>
1139 requires (__constructible_from_tuple_like<_UTuple>())
1140 && (!__use_other_ctor<_UTuple>())
1141 && (__dangles_from_tuple_like<_UTuple>())
1142 tuple(_UTuple&&) = delete;
1145 // Allocator-extended constructors.
1147 template<typename _Alloc>
1149 explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
1150 tuple(allocator_arg_t __tag, const _Alloc& __a)
1151 requires (is_default_constructible_v<_Elements> && ...)
1152 : _Inherited(__tag, __a)
1155 template<typename _Alloc>
1156 constexpr explicit(!__convertible<const _Elements&...>())
1157 tuple(allocator_arg_t __tag, const _Alloc& __a,
1158 const _Elements&... __elements)
1159 requires (__constructible<const _Elements&...>())
1160 : _Inherited(__tag, __a, __elements...)
1163 template<typename _Alloc, typename... _UTypes>
1164 requires (__disambiguating_constraint<_UTypes...>())
1165 && (__constructible<_UTypes...>())
1166 && (!__dangles<_UTypes...>())
1167 constexpr explicit(!__convertible<_UTypes...>())
1168 tuple(allocator_arg_t __tag, const _Alloc& __a, _UTypes&&... __u)
1169 : _Inherited(__tag, __a, std::forward<_UTypes>(__u)...)
1172 template<typename _Alloc, typename... _UTypes>
1173 requires (__disambiguating_constraint<_UTypes...>())
1174 && (__constructible<_UTypes...>())
1175 && (__dangles<_UTypes...>())
1176 tuple(allocator_arg_t, const _Alloc&, _UTypes&&...) = delete;
1178 template<typename _Alloc>
1180 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __u)
1181 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__u))
1184 template<typename _Alloc>
1185 requires (__constructible<_Elements...>())
1187 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __u)
1188 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__u))
1191 template<typename _Alloc, typename... _UTypes>
1192 requires (__constructible<const _UTypes&...>())
1193 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1194 && (!__dangles<const _UTypes&...>())
1195 constexpr explicit(!__convertible<const _UTypes&...>())
1196 tuple(allocator_arg_t __tag, const _Alloc& __a,
1197 const tuple<_UTypes...>& __u)
1198 : _Inherited(__tag, __a,
1199 static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1202 template<typename _Alloc, typename... _UTypes>
1203 requires (__constructible<const _UTypes&...>())
1204 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1205 && (__dangles<const _UTypes&...>())
1206 tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&) = delete;
1208 template<typename _Alloc, typename... _UTypes>
1209 requires (__constructible<_UTypes...>())
1210 && (!__use_other_ctor<tuple<_UTypes...>>())
1211 && (!__dangles<_UTypes...>())
1212 constexpr explicit(!__use_other_ctor<tuple<_UTypes...>>())
1213 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>&& __u)
1214 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1217 template<typename _Alloc, typename... _UTypes>
1218 requires (__constructible<_UTypes...>())
1219 && (!__use_other_ctor<tuple<_UTypes...>>())
1220 && (__dangles<_UTypes...>())
1221 tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&&) = delete;
1223 #if __cpp_lib_ranges_zip // >= C++23
1224 template<typename _Alloc, typename... _UTypes>
1225 requires (__constructible<_UTypes&...>())
1226 && (!__use_other_ctor<tuple<_UTypes...>&>())
1227 && (!__dangles<_UTypes&...>())
1228 constexpr explicit(!__convertible<_UTypes&...>())
1229 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>& __u)
1230 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1233 template<typename _Alloc, typename... _UTypes>
1234 requires (__constructible<_UTypes&...>())
1235 && (!__use_other_ctor<tuple<_UTypes...>&>())
1236 && (__dangles<_UTypes&...>())
1237 tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&) = delete;
1239 template<typename _Alloc, typename... _UTypes>
1240 requires (__constructible<const _UTypes...>())
1241 && (!__use_other_ctor<const tuple<_UTypes...>>())
1242 && (!__dangles<const _UTypes...>())
1243 constexpr explicit(!__convertible<const _UTypes...>())
1244 tuple(allocator_arg_t __tag, const _Alloc& __a,
1245 const tuple<_UTypes...>&& __u)
1246 : _Inherited(__tag, __a,
1247 static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1250 template<typename _Alloc, typename... _UTypes>
1251 requires (__constructible<const _UTypes...>())
1252 && (!__use_other_ctor<const tuple<_UTypes...>>())
1253 && (__dangles<const _UTypes...>())
1254 tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&&) = delete;
1257 template<typename _Alloc, typename _U1, typename _U2>
1258 requires (sizeof...(_Elements) == 2)
1259 && (__constructible<const _U1&, const _U2&>())
1260 && (!__dangles<const _U1&, const _U2&>())
1261 constexpr explicit(!__convertible<const _U1&, const _U2&>())
1262 tuple(allocator_arg_t __tag, const _Alloc& __a,
1263 const pair<_U1, _U2>& __u)
1264 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1265 : _Inherited(__tag, __a, __u.first, __u.second)
1268 template<typename _Alloc, typename _U1, typename _U2>
1269 requires (sizeof...(_Elements) == 2)
1270 && (__constructible<const _U1&, const _U2&>())
1271 && (__dangles<const _U1&, const _U2&>())
1272 tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&) = delete;
1274 template<typename _Alloc, typename _U1, typename _U2>
1275 requires (sizeof...(_Elements) == 2)
1276 && (__constructible<_U1, _U2>())
1277 && (!__dangles<_U1, _U2>())
1278 constexpr explicit(!__convertible<_U1, _U2>())
1279 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __u)
1280 noexcept(__nothrow_constructible<_U1, _U2>())
1281 : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1284 template<typename _Alloc, typename _U1, typename _U2>
1285 requires (sizeof...(_Elements) == 2)
1286 && (__constructible<_U1, _U2>())
1287 && (__dangles<_U1, _U2>())
1288 tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&) = delete;
1290 #if __cpp_lib_ranges_zip // >= C++23
1291 template<typename _Alloc, typename _U1, typename _U2>
1292 requires (sizeof...(_Elements) == 2)
1293 && (__constructible<_U1&, _U2&>())
1294 && (!__dangles<_U1&, _U2&>())
1295 constexpr explicit(!__convertible<_U1&, _U2&>())
1296 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>& __u)
1297 noexcept(__nothrow_constructible<_U1&, _U2&>())
1298 : _Inherited(__tag, __a, __u.first, __u.second)
1301 template<typename _Alloc, typename _U1, typename _U2>
1302 requires (sizeof...(_Elements) == 2)
1303 && (__constructible<_U1&, _U2&>())
1304 && (__dangles<_U1&, _U2&>())
1305 tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&) = delete;
1307 template<typename _Alloc, typename _U1, typename _U2>
1308 requires (sizeof...(_Elements) == 2)
1309 && (__constructible<const _U1, const _U2>())
1310 && (!__dangles<const _U1, const _U2>())
1311 constexpr explicit(!__convertible<const _U1, const _U2>())
1312 tuple(allocator_arg_t __tag, const _Alloc& __a,
1313 const pair<_U1, _U2>&& __u)
1314 noexcept(__nothrow_constructible<const _U1, const _U2>())
1315 : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1318 template<typename _Alloc, typename _U1, typename _U2>
1319 requires (sizeof...(_Elements) == 2)
1320 && (__constructible<const _U1, const _U2>())
1321 && (__dangles<const _U1, const _U2>())
1322 tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&&) = delete;
1325 #if __cpp_lib_tuple_like // >= C++23
1326 template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
1327 requires (__constructible_from_tuple_like<_UTuple>())
1328 && (!__use_other_ctor<_UTuple>())
1329 && (!__dangles_from_tuple_like<_UTuple>())
1330 constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
1331 tuple(allocator_arg_t __tag, const _Alloc& __a, _UTuple&& __u)
1332 : _Inherited(__tuple_like_tag_t{},
1333 __tag, __a, std::forward<_UTuple>(__u),
1334 index_sequence_for<_Elements...>{})
1337 template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
1338 requires (__constructible_from_tuple_like<_UTuple>())
1339 && (!__use_other_ctor<_UTuple>())
1340 && (__dangles_from_tuple_like<_UTuple>())
1341 tuple(allocator_arg_t, const _Alloc&, _UTuple&&) = delete;
1344 #else // !(concepts && conditional_explicit)
1346 template<bool _Cond>
1347 using _TCC = _TupleConstraints<_Cond, _Elements...>;
1349 // Constraint for non-explicit default constructor
1350 template<bool _Dummy>
1351 using _ImplicitDefaultCtor = __enable_if_t<
1352 _TCC<_Dummy>::__is_implicitly_default_constructible(),
1355 // Constraint for explicit default constructor
1356 template<bool _Dummy>
1357 using _ExplicitDefaultCtor = __enable_if_t<
1358 _TCC<_Dummy>::__is_explicitly_default_constructible(),
1361 // Constraint for non-explicit constructors
1362 template<bool _Cond, typename... _Args>
1363 using _ImplicitCtor = __enable_if_t<
1364 _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
1367 // Constraint for non-explicit constructors
1368 template<bool _Cond, typename... _Args>
1369 using _ExplicitCtor = __enable_if_t<
1370 _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
1373 // Condition for noexcept-specifier of a constructor.
1374 template<typename... _UElements>
1375 static constexpr bool __nothrow_constructible()
1378 __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
1381 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1.
1382 template<typename _Up>
1383 static constexpr bool __valid_args()
1385 return sizeof...(_Elements) == 1
1386 && !is_same<tuple, __remove_cvref_t<_Up>>::value;
1389 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1.
1390 template<typename, typename, typename... _Tail>
1391 static constexpr bool __valid_args()
1392 { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); }
1394 /* Constraint for constructors with a tuple<UTypes...> parameter ensures
1395 * that the constructor is only viable when it would not interfere with
1396 * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&).
1397 * Such constructors are only viable if:
1398 * either sizeof...(Types) != 1,
1399 * or (when Types... expands to T and UTypes... expands to U)
1400 * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>,
1401 * and is_same_v<T, U> are all false.
1403 template<typename _Tuple, typename = tuple,
1404 typename = __remove_cvref_t<_Tuple>>
1405 struct _UseOtherCtor
1408 // If TUPLE is convertible to the single element in *this,
1409 // then TUPLE should match tuple(UTypes&&...) instead.
1410 template<typename _Tuple, typename _Tp, typename _Up>
1411 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>>
1412 : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>::type
1414 // If TUPLE and *this each have a single element of the same type,
1415 // then TUPLE should match a copy/move constructor instead.
1416 template<typename _Tuple, typename _Tp>
1417 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>>
1421 // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
1422 // and the single element in Types can be initialized from TUPLE,
1423 // or is the same type as tuple_element_t<0, TUPLE>.
1424 template<typename _Tuple>
1425 static constexpr bool __use_other_ctor()
1426 { return _UseOtherCtor<_Tuple>::value; }
1428 /// @cond undocumented
1429 #undef __glibcxx_no_dangling_refs
1430 #if __has_builtin(__reference_constructs_from_temporary) \
1431 && defined _GLIBCXX_DEBUG
1432 // Error if construction from U... would create a dangling ref.
1433 # if __cpp_fold_expressions
1434 # define __glibcxx_dangling_refs(U) \
1435 (__reference_constructs_from_temporary(_Elements, U) || ...)
1437 # define __glibcxx_dangling_refs(U) \
1438 __or_<__bool_constant<__reference_constructs_from_temporary(_Elements, U) \
1441 # define __glibcxx_no_dangling_refs(U) \
1442 static_assert(!__glibcxx_dangling_refs(U), \
1443 "std::tuple constructor creates a dangling reference")
1445 # define __glibcxx_no_dangling_refs(U)
1450 template<typename _Dummy = void,
1451 _ImplicitDefaultCtor<is_void<_Dummy>::value> = true>
1454 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1457 template<typename _Dummy = void,
1458 _ExplicitDefaultCtor<is_void<_Dummy>::value> = false>
1461 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1464 template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1465 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1467 tuple(const _Elements&... __elements)
1468 noexcept(__nothrow_constructible<const _Elements&...>())
1469 : _Inherited(__elements...) { }
1471 template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1472 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1474 tuple(const _Elements&... __elements)
1475 noexcept(__nothrow_constructible<const _Elements&...>())
1476 : _Inherited(__elements...) { }
1478 template<typename... _UElements,
1479 bool _Valid = __valid_args<_UElements...>(),
1480 _ImplicitCtor<_Valid, _UElements...> = true>
1482 tuple(_UElements&&... __elements)
1483 noexcept(__nothrow_constructible<_UElements...>())
1484 : _Inherited(std::forward<_UElements>(__elements)...)
1485 { __glibcxx_no_dangling_refs(_UElements&&); }
1487 template<typename... _UElements,
1488 bool _Valid = __valid_args<_UElements...>(),
1489 _ExplicitCtor<_Valid, _UElements...> = false>
1491 tuple(_UElements&&... __elements)
1492 noexcept(__nothrow_constructible<_UElements...>())
1493 : _Inherited(std::forward<_UElements>(__elements)...)
1494 { __glibcxx_no_dangling_refs(_UElements&&); }
1496 constexpr tuple(const tuple&) = default;
1498 constexpr tuple(tuple&&) = default;
1500 template<typename... _UElements,
1501 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1502 && !__use_other_ctor<const tuple<_UElements...>&>(),
1503 _ImplicitCtor<_Valid, const _UElements&...> = true>
1505 tuple(const tuple<_UElements...>& __in)
1506 noexcept(__nothrow_constructible<const _UElements&...>())
1507 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1508 { __glibcxx_no_dangling_refs(const _UElements&); }
1510 template<typename... _UElements,
1511 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1512 && !__use_other_ctor<const tuple<_UElements...>&>(),
1513 _ExplicitCtor<_Valid, const _UElements&...> = false>
1515 tuple(const tuple<_UElements...>& __in)
1516 noexcept(__nothrow_constructible<const _UElements&...>())
1517 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1518 { __glibcxx_no_dangling_refs(const _UElements&); }
1520 template<typename... _UElements,
1521 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1522 && !__use_other_ctor<tuple<_UElements...>&&>(),
1523 _ImplicitCtor<_Valid, _UElements...> = true>
1525 tuple(tuple<_UElements...>&& __in)
1526 noexcept(__nothrow_constructible<_UElements...>())
1527 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1528 { __glibcxx_no_dangling_refs(_UElements&&); }
1530 template<typename... _UElements,
1531 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1532 && !__use_other_ctor<tuple<_UElements...>&&>(),
1533 _ExplicitCtor<_Valid, _UElements...> = false>
1535 tuple(tuple<_UElements...>&& __in)
1536 noexcept(__nothrow_constructible<_UElements...>())
1537 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1538 { __glibcxx_no_dangling_refs(_UElements&&); }
1540 // Allocator-extended constructors.
1542 template<typename _Alloc,
1543 _ImplicitDefaultCtor<is_object<_Alloc>::value> = true>
1544 _GLIBCXX20_CONSTEXPR
1545 tuple(allocator_arg_t __tag, const _Alloc& __a)
1546 : _Inherited(__tag, __a) { }
1548 template<typename _Alloc,
1549 _ExplicitDefaultCtor<is_object<_Alloc>::value> = false>
1550 _GLIBCXX20_CONSTEXPR
1552 tuple(allocator_arg_t __tag, const _Alloc& __a)
1553 : _Inherited(__tag, __a) { }
1555 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1556 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1557 _GLIBCXX20_CONSTEXPR
1558 tuple(allocator_arg_t __tag, const _Alloc& __a,
1559 const _Elements&... __elements)
1560 : _Inherited(__tag, __a, __elements...) { }
1562 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1563 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1564 _GLIBCXX20_CONSTEXPR
1566 tuple(allocator_arg_t __tag, const _Alloc& __a,
1567 const _Elements&... __elements)
1568 : _Inherited(__tag, __a, __elements...) { }
1570 template<typename _Alloc, typename... _UElements,
1571 bool _Valid = __valid_args<_UElements...>(),
1572 _ImplicitCtor<_Valid, _UElements...> = true>
1573 _GLIBCXX20_CONSTEXPR
1574 tuple(allocator_arg_t __tag, const _Alloc& __a,
1575 _UElements&&... __elements)
1576 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1577 { __glibcxx_no_dangling_refs(_UElements&&); }
1579 template<typename _Alloc, typename... _UElements,
1580 bool _Valid = __valid_args<_UElements...>(),
1581 _ExplicitCtor<_Valid, _UElements...> = false>
1582 _GLIBCXX20_CONSTEXPR
1584 tuple(allocator_arg_t __tag, const _Alloc& __a,
1585 _UElements&&... __elements)
1586 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1587 { __glibcxx_no_dangling_refs(_UElements&&); }
1589 template<typename _Alloc>
1590 _GLIBCXX20_CONSTEXPR
1591 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1592 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1594 template<typename _Alloc>
1595 _GLIBCXX20_CONSTEXPR
1596 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1597 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1599 template<typename _Alloc, typename... _UElements,
1600 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1601 && !__use_other_ctor<const tuple<_UElements...>&>(),
1602 _ImplicitCtor<_Valid, const _UElements&...> = true>
1603 _GLIBCXX20_CONSTEXPR
1604 tuple(allocator_arg_t __tag, const _Alloc& __a,
1605 const tuple<_UElements...>& __in)
1606 : _Inherited(__tag, __a,
1607 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1608 { __glibcxx_no_dangling_refs(const _UElements&); }
1610 template<typename _Alloc, typename... _UElements,
1611 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1612 && !__use_other_ctor<const tuple<_UElements...>&>(),
1613 _ExplicitCtor<_Valid, const _UElements&...> = false>
1614 _GLIBCXX20_CONSTEXPR
1616 tuple(allocator_arg_t __tag, const _Alloc& __a,
1617 const tuple<_UElements...>& __in)
1618 : _Inherited(__tag, __a,
1619 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1620 { __glibcxx_no_dangling_refs(const _UElements&); }
1622 template<typename _Alloc, typename... _UElements,
1623 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1624 && !__use_other_ctor<tuple<_UElements...>&&>(),
1625 _ImplicitCtor<_Valid, _UElements...> = true>
1626 _GLIBCXX20_CONSTEXPR
1627 tuple(allocator_arg_t __tag, const _Alloc& __a,
1628 tuple<_UElements...>&& __in)
1629 : _Inherited(__tag, __a,
1630 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1631 { __glibcxx_no_dangling_refs(_UElements&&); }
1633 template<typename _Alloc, typename... _UElements,
1634 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1635 && !__use_other_ctor<tuple<_UElements...>&&>(),
1636 _ExplicitCtor<_Valid, _UElements...> = false>
1637 _GLIBCXX20_CONSTEXPR
1639 tuple(allocator_arg_t __tag, const _Alloc& __a,
1640 tuple<_UElements...>&& __in)
1641 : _Inherited(__tag, __a,
1642 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1643 { __glibcxx_no_dangling_refs(_UElements&&); }
1644 #endif // concepts && conditional_explicit
1648 #if __cpp_concepts && __cpp_consteval // >= C++20
1650 template<typename... _UTypes>
1651 static consteval bool
1654 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1655 return __and_v<is_assignable<_Elements&, _UTypes>...>;
1660 template<typename... _UTypes>
1661 static consteval bool
1662 __nothrow_assignable()
1664 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1665 return __and_v<is_nothrow_assignable<_Elements&, _UTypes>...>;
1670 #if __cpp_lib_ranges_zip // >= C++23
1671 template<typename... _UTypes>
1672 static consteval bool
1673 __const_assignable()
1675 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1676 return __and_v<is_assignable<const _Elements&, _UTypes>...>;
1682 #if __cpp_lib_tuple_like // >= C++23
1683 template<typename _UTuple>
1684 static consteval bool
1685 __assignable_from_tuple_like()
1687 return []<size_t... _Is>(index_sequence<_Is...>) {
1688 return __assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1689 }(index_sequence_for<_Elements...>{});
1692 template<typename _UTuple>
1693 static consteval bool
1694 __const_assignable_from_tuple_like()
1696 return []<size_t... _Is>(index_sequence<_Is...>) {
1697 return __const_assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1698 }(index_sequence_for<_Elements...>{});
1704 tuple& operator=(const tuple& __u) = delete;
1707 operator=(const tuple& __u)
1708 noexcept(__nothrow_assignable<const _Elements&...>())
1709 requires (__assignable<const _Elements&...>())
1711 this->_M_assign(__u);
1716 operator=(tuple&& __u)
1717 noexcept(__nothrow_assignable<_Elements...>())
1718 requires (__assignable<_Elements...>())
1720 this->_M_assign(std::move(__u));
1724 template<typename... _UTypes>
1725 requires (__assignable<const _UTypes&...>())
1727 operator=(const tuple<_UTypes...>& __u)
1728 noexcept(__nothrow_assignable<const _UTypes&...>())
1730 this->_M_assign(__u);
1734 template<typename... _UTypes>
1735 requires (__assignable<_UTypes...>())
1737 operator=(tuple<_UTypes...>&& __u)
1738 noexcept(__nothrow_assignable<_UTypes...>())
1740 this->_M_assign(std::move(__u));
1744 #if __cpp_lib_ranges_zip // >= C++23
1745 constexpr const tuple&
1746 operator=(const tuple& __u) const
1747 requires (__const_assignable<const _Elements&...>())
1749 this->_M_assign(__u);
1753 constexpr const tuple&
1754 operator=(tuple&& __u) const
1755 requires (__const_assignable<_Elements...>())
1757 this->_M_assign(std::move(__u));
1761 template<typename... _UTypes>
1762 constexpr const tuple&
1763 operator=(const tuple<_UTypes...>& __u) const
1764 requires (__const_assignable<const _UTypes&...>())
1766 this->_M_assign(__u);
1770 template<typename... _UTypes>
1771 constexpr const tuple&
1772 operator=(tuple<_UTypes...>&& __u) const
1773 requires (__const_assignable<_UTypes...>())
1775 this->_M_assign(std::move(__u));
1780 template<typename _U1, typename _U2>
1781 requires (__assignable<const _U1&, const _U2&>())
1783 operator=(const pair<_U1, _U2>& __u)
1784 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1786 this->_M_head(*this) = __u.first;
1787 this->_M_tail(*this)._M_head(*this) = __u.second;
1791 template<typename _U1, typename _U2>
1792 requires (__assignable<_U1, _U2>())
1794 operator=(pair<_U1, _U2>&& __u)
1795 noexcept(__nothrow_assignable<_U1, _U2>())
1797 this->_M_head(*this) = std::forward<_U1>(__u.first);
1798 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1802 #if __cpp_lib_ranges_zip // >= C++23
1803 template<typename _U1, typename _U2>
1804 requires (__const_assignable<const _U1&, const _U2>())
1805 constexpr const tuple&
1806 operator=(const pair<_U1, _U2>& __u) const
1808 this->_M_head(*this) = __u.first;
1809 this->_M_tail(*this)._M_head(*this) = __u.second;
1813 template<typename _U1, typename _U2>
1814 requires (__const_assignable<_U1, _U2>())
1815 constexpr const tuple&
1816 operator=(pair<_U1, _U2>&& __u) const
1818 this->_M_head(*this) = std::forward<_U1>(__u.first);
1819 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1824 #if __cpp_lib_tuple_like // >= C++23
1825 template<__eligible_tuple_like<tuple> _UTuple>
1826 requires (__assignable_from_tuple_like<_UTuple>())
1828 operator=(_UTuple&& __u)
1830 this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1834 template<__eligible_tuple_like<tuple> _UTuple>
1835 requires (__const_assignable_from_tuple_like<_UTuple>())
1836 constexpr const tuple&
1837 operator=(_UTuple&& __u) const
1839 this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1843 template<__tuple_like _UTuple>
1844 requires (!__is_tuple_v<_UTuple>)
1845 friend constexpr bool
1846 operator== [[nodiscard]] (const tuple& __t, const _UTuple& __u)
1848 static_assert(sizeof...(_Elements) == tuple_size_v<_UTuple>,
1849 "tuple objects can only be compared if they have equal sizes.");
1850 return [&]<size_t... _Is>(index_sequence<_Is...>) {
1851 return (bool(std::get<_Is>(__t) == std::get<_Is>(__u))
1853 }(index_sequence_for<_Elements...>{});
1856 template<__tuple_like _UTuple,
1857 typename = make_index_sequence<tuple_size_v<_UTuple>>>
1858 struct __tuple_like_common_comparison_category;
1860 template<__tuple_like _UTuple, size_t... _Is>
1862 { typename void_t<__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>; }
1863 struct __tuple_like_common_comparison_category<_UTuple, index_sequence<_Is...>>
1865 using type = common_comparison_category_t
1866 <__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>;
1869 template<__tuple_like _UTuple>
1870 requires (!__is_tuple_v<_UTuple>)
1871 friend constexpr typename __tuple_like_common_comparison_category<_UTuple>::type
1872 operator<=>(const tuple& __t, const _UTuple& __u)
1874 using _Cat = typename __tuple_like_common_comparison_category<_UTuple>::type;
1875 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Elements...>());
1879 #else // ! (concepts && consteval)
1882 template<typename... _UElements>
1884 __enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
1886 { return __and_<is_assignable<_Elements&, _UElements>...>::value; }
1888 // Condition for noexcept-specifier of an assignment operator.
1889 template<typename... _UElements>
1890 static constexpr bool __nothrow_assignable()
1893 __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
1898 _GLIBCXX20_CONSTEXPR
1900 operator=(__conditional_t<__assignable<const _Elements&...>(),
1902 const __nonesuch&> __in)
1903 noexcept(__nothrow_assignable<const _Elements&...>())
1905 this->_M_assign(__in);
1909 _GLIBCXX20_CONSTEXPR
1911 operator=(__conditional_t<__assignable<_Elements...>(),
1914 noexcept(__nothrow_assignable<_Elements...>())
1916 this->_M_assign(std::move(__in));
1920 template<typename... _UElements>
1921 _GLIBCXX20_CONSTEXPR
1922 __enable_if_t<__assignable<const _UElements&...>(), tuple&>
1923 operator=(const tuple<_UElements...>& __in)
1924 noexcept(__nothrow_assignable<const _UElements&...>())
1926 this->_M_assign(__in);
1930 template<typename... _UElements>
1931 _GLIBCXX20_CONSTEXPR
1932 __enable_if_t<__assignable<_UElements...>(), tuple&>
1933 operator=(tuple<_UElements...>&& __in)
1934 noexcept(__nothrow_assignable<_UElements...>())
1936 this->_M_assign(std::move(__in));
1939 #endif // concepts && consteval
1942 _GLIBCXX20_CONSTEXPR
1945 noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
1946 { _Inherited::_M_swap(__in); }
1948 #if __cpp_lib_ranges_zip // >= C++23
1949 // As an extension, we constrain the const swap member function in order
1950 // to continue accepting explicit instantiation of tuples whose elements
1951 // are not all const swappable. Without this constraint, such an
1952 // explicit instantiation would also instantiate the ill-formed body of
1953 // this function and yield a hard error. This constraint shouldn't
1954 // affect the behavior of valid programs.
1956 swap(const tuple& __in) const
1957 noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
1958 requires (is_swappable_v<const _Elements> && ...)
1959 { _Inherited::_M_swap(__in); }
1963 #if __cpp_deduction_guides >= 201606
1964 template<typename... _UTypes>
1965 tuple(_UTypes...) -> tuple<_UTypes...>;
1966 template<typename _T1, typename _T2>
1967 tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
1968 template<typename _Alloc, typename... _UTypes>
1969 tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
1970 template<typename _Alloc, typename _T1, typename _T2>
1971 tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
1972 template<typename _Alloc, typename... _UTypes>
1973 tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
1976 // Explicit specialization, zero-element tuple.
1981 _GLIBCXX20_CONSTEXPR
1982 void swap(tuple&) noexcept { /* no-op */ }
1983 #if __cpp_lib_ranges_zip // >= C++23
1984 constexpr void swap(const tuple&) const noexcept { /* no-op */ }
1986 // We need the default since we're going to define no-op
1987 // allocator constructors.
1989 // No-op allocator constructors.
1990 template<typename _Alloc>
1991 _GLIBCXX20_CONSTEXPR
1992 tuple(allocator_arg_t, const _Alloc&) noexcept { }
1993 template<typename _Alloc>
1994 _GLIBCXX20_CONSTEXPR
1995 tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
1998 #if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20
1999 /// Partial specialization, 2-element tuple.
2000 /// Includes construction and assignment from a pair.
2001 template<typename _T1, typename _T2>
2002 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
2004 typedef _Tuple_impl<0, _T1, _T2> _Inherited;
2006 // Constraint for non-explicit default constructor
2007 template<bool _Dummy, typename _U1, typename _U2>
2008 using _ImplicitDefaultCtor = __enable_if_t<
2009 _TupleConstraints<_Dummy, _U1, _U2>::
2010 __is_implicitly_default_constructible(),
2013 // Constraint for explicit default constructor
2014 template<bool _Dummy, typename _U1, typename _U2>
2015 using _ExplicitDefaultCtor = __enable_if_t<
2016 _TupleConstraints<_Dummy, _U1, _U2>::
2017 __is_explicitly_default_constructible(),
2020 template<bool _Dummy>
2021 using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
2023 // Constraint for non-explicit constructors
2024 template<bool _Cond, typename _U1, typename _U2>
2025 using _ImplicitCtor = __enable_if_t<
2026 _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
2029 // Constraint for non-explicit constructors
2030 template<bool _Cond, typename _U1, typename _U2>
2031 using _ExplicitCtor = __enable_if_t<
2032 _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
2035 template<typename _U1, typename _U2>
2036 static constexpr bool __assignable()
2038 return __and_<is_assignable<_T1&, _U1>,
2039 is_assignable<_T2&, _U2>>::value;
2042 template<typename _U1, typename _U2>
2043 static constexpr bool __nothrow_assignable()
2045 return __and_<is_nothrow_assignable<_T1&, _U1>,
2046 is_nothrow_assignable<_T2&, _U2>>::value;
2049 template<typename _U1, typename _U2>
2050 static constexpr bool __nothrow_constructible()
2052 return __and_<is_nothrow_constructible<_T1, _U1>,
2053 is_nothrow_constructible<_T2, _U2>>::value;
2056 static constexpr bool __nothrow_default_constructible()
2058 return __and_<is_nothrow_default_constructible<_T1>,
2059 is_nothrow_default_constructible<_T2>>::value;
2062 template<typename _U1>
2063 static constexpr bool __is_alloc_arg()
2064 { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
2066 /// @cond undocumented
2067 #undef __glibcxx_no_dangling_refs
2068 // Error if construction from _U1 and _U2 would create a dangling ref.
2069 #if __has_builtin(__reference_constructs_from_temporary) \
2070 && defined _GLIBCXX_DEBUG
2071 # define __glibcxx_no_dangling_refs(_U1, _U2) \
2072 static_assert(!__reference_constructs_from_temporary(_T1, _U1) \
2073 && !__reference_constructs_from_temporary(_T2, _U2), \
2074 "std::tuple constructor creates a dangling reference")
2076 # define __glibcxx_no_dangling_refs(_U1, _U2)
2081 template<bool _Dummy = true,
2082 _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
2085 noexcept(__nothrow_default_constructible())
2088 template<bool _Dummy = true,
2089 _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
2092 noexcept(__nothrow_default_constructible())
2095 template<bool _Dummy = true,
2096 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2098 tuple(const _T1& __a1, const _T2& __a2)
2099 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2100 : _Inherited(__a1, __a2) { }
2102 template<bool _Dummy = true,
2103 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2105 tuple(const _T1& __a1, const _T2& __a2)
2106 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2107 : _Inherited(__a1, __a2) { }
2109 template<typename _U1, typename _U2,
2110 _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
2112 tuple(_U1&& __a1, _U2&& __a2)
2113 noexcept(__nothrow_constructible<_U1, _U2>())
2114 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2115 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2117 template<typename _U1, typename _U2,
2118 _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
2120 tuple(_U1&& __a1, _U2&& __a2)
2121 noexcept(__nothrow_constructible<_U1, _U2>())
2122 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2123 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2125 constexpr tuple(const tuple&) = default;
2127 constexpr tuple(tuple&&) = default;
2129 template<typename _U1, typename _U2,
2130 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2132 tuple(const tuple<_U1, _U2>& __in)
2133 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2134 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2135 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2137 template<typename _U1, typename _U2,
2138 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2140 tuple(const tuple<_U1, _U2>& __in)
2141 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2142 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2143 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2145 template<typename _U1, typename _U2,
2146 _ImplicitCtor<true, _U1, _U2> = true>
2148 tuple(tuple<_U1, _U2>&& __in)
2149 noexcept(__nothrow_constructible<_U1, _U2>())
2150 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2151 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2153 template<typename _U1, typename _U2,
2154 _ExplicitCtor<true, _U1, _U2> = false>
2156 tuple(tuple<_U1, _U2>&& __in)
2157 noexcept(__nothrow_constructible<_U1, _U2>())
2158 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2159 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2161 template<typename _U1, typename _U2,
2162 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2164 tuple(const pair<_U1, _U2>& __in)
2165 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2166 : _Inherited(__in.first, __in.second)
2167 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2169 template<typename _U1, typename _U2,
2170 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2172 tuple(const pair<_U1, _U2>& __in)
2173 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2174 : _Inherited(__in.first, __in.second)
2175 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2177 template<typename _U1, typename _U2,
2178 _ImplicitCtor<true, _U1, _U2> = true>
2180 tuple(pair<_U1, _U2>&& __in)
2181 noexcept(__nothrow_constructible<_U1, _U2>())
2182 : _Inherited(std::forward<_U1>(__in.first),
2183 std::forward<_U2>(__in.second))
2184 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2186 template<typename _U1, typename _U2,
2187 _ExplicitCtor<true, _U1, _U2> = false>
2189 tuple(pair<_U1, _U2>&& __in)
2190 noexcept(__nothrow_constructible<_U1, _U2>())
2191 : _Inherited(std::forward<_U1>(__in.first),
2192 std::forward<_U2>(__in.second))
2193 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2195 // Allocator-extended constructors.
2197 template<typename _Alloc,
2198 _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
2199 _GLIBCXX20_CONSTEXPR
2200 tuple(allocator_arg_t __tag, const _Alloc& __a)
2201 : _Inherited(__tag, __a) { }
2203 template<typename _Alloc,
2204 _ExplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = false>
2205 _GLIBCXX20_CONSTEXPR
2207 tuple(allocator_arg_t __tag, const _Alloc& __a)
2208 : _Inherited(__tag, __a) { }
2210 template<typename _Alloc, bool _Dummy = true,
2211 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2212 _GLIBCXX20_CONSTEXPR
2213 tuple(allocator_arg_t __tag, const _Alloc& __a,
2214 const _T1& __a1, const _T2& __a2)
2215 : _Inherited(__tag, __a, __a1, __a2) { }
2217 template<typename _Alloc, bool _Dummy = true,
2218 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2220 _GLIBCXX20_CONSTEXPR
2221 tuple(allocator_arg_t __tag, const _Alloc& __a,
2222 const _T1& __a1, const _T2& __a2)
2223 : _Inherited(__tag, __a, __a1, __a2) { }
2225 template<typename _Alloc, typename _U1, typename _U2,
2226 _ImplicitCtor<true, _U1, _U2> = true>
2227 _GLIBCXX20_CONSTEXPR
2228 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
2229 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2230 std::forward<_U2>(__a2))
2231 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2233 template<typename _Alloc, typename _U1, typename _U2,
2234 _ExplicitCtor<true, _U1, _U2> = false>
2236 _GLIBCXX20_CONSTEXPR
2237 tuple(allocator_arg_t __tag, const _Alloc& __a,
2238 _U1&& __a1, _U2&& __a2)
2239 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2240 std::forward<_U2>(__a2))
2241 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2243 template<typename _Alloc>
2244 _GLIBCXX20_CONSTEXPR
2245 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
2246 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
2248 template<typename _Alloc>
2249 _GLIBCXX20_CONSTEXPR
2250 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
2251 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
2253 template<typename _Alloc, typename _U1, typename _U2,
2254 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2255 _GLIBCXX20_CONSTEXPR
2256 tuple(allocator_arg_t __tag, const _Alloc& __a,
2257 const tuple<_U1, _U2>& __in)
2258 : _Inherited(__tag, __a,
2259 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2260 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2262 template<typename _Alloc, typename _U1, typename _U2,
2263 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2265 _GLIBCXX20_CONSTEXPR
2266 tuple(allocator_arg_t __tag, const _Alloc& __a,
2267 const tuple<_U1, _U2>& __in)
2268 : _Inherited(__tag, __a,
2269 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2270 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2272 template<typename _Alloc, typename _U1, typename _U2,
2273 _ImplicitCtor<true, _U1, _U2> = true>
2274 _GLIBCXX20_CONSTEXPR
2275 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2276 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2277 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2279 template<typename _Alloc, typename _U1, typename _U2,
2280 _ExplicitCtor<true, _U1, _U2> = false>
2282 _GLIBCXX20_CONSTEXPR
2283 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2284 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2285 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2287 template<typename _Alloc, typename _U1, typename _U2,
2288 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2289 _GLIBCXX20_CONSTEXPR
2290 tuple(allocator_arg_t __tag, const _Alloc& __a,
2291 const pair<_U1, _U2>& __in)
2292 : _Inherited(__tag, __a, __in.first, __in.second)
2293 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2295 template<typename _Alloc, typename _U1, typename _U2,
2296 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2298 _GLIBCXX20_CONSTEXPR
2299 tuple(allocator_arg_t __tag, const _Alloc& __a,
2300 const pair<_U1, _U2>& __in)
2301 : _Inherited(__tag, __a, __in.first, __in.second)
2302 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2304 template<typename _Alloc, typename _U1, typename _U2,
2305 _ImplicitCtor<true, _U1, _U2> = true>
2306 _GLIBCXX20_CONSTEXPR
2307 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2308 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2309 std::forward<_U2>(__in.second))
2310 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2312 template<typename _Alloc, typename _U1, typename _U2,
2313 _ExplicitCtor<true, _U1, _U2> = false>
2315 _GLIBCXX20_CONSTEXPR
2316 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2317 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2318 std::forward<_U2>(__in.second))
2319 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2321 // Tuple assignment.
2323 _GLIBCXX20_CONSTEXPR
2325 operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
2327 const __nonesuch&> __in)
2328 noexcept(__nothrow_assignable<const _T1&, const _T2&>())
2330 this->_M_assign(__in);
2334 _GLIBCXX20_CONSTEXPR
2336 operator=(__conditional_t<__assignable<_T1, _T2>(),
2339 noexcept(__nothrow_assignable<_T1, _T2>())
2341 this->_M_assign(std::move(__in));
2345 template<typename _U1, typename _U2>
2346 _GLIBCXX20_CONSTEXPR
2347 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2348 operator=(const tuple<_U1, _U2>& __in)
2349 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2351 this->_M_assign(__in);
2355 template<typename _U1, typename _U2>
2356 _GLIBCXX20_CONSTEXPR
2357 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2358 operator=(tuple<_U1, _U2>&& __in)
2359 noexcept(__nothrow_assignable<_U1, _U2>())
2361 this->_M_assign(std::move(__in));
2365 template<typename _U1, typename _U2>
2366 _GLIBCXX20_CONSTEXPR
2367 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2368 operator=(const pair<_U1, _U2>& __in)
2369 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2371 this->_M_head(*this) = __in.first;
2372 this->_M_tail(*this)._M_head(*this) = __in.second;
2376 template<typename _U1, typename _U2>
2377 _GLIBCXX20_CONSTEXPR
2378 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2379 operator=(pair<_U1, _U2>&& __in)
2380 noexcept(__nothrow_assignable<_U1, _U2>())
2382 this->_M_head(*this) = std::forward<_U1>(__in.first);
2383 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
2387 _GLIBCXX20_CONSTEXPR
2390 noexcept(__and_<__is_nothrow_swappable<_T1>,
2391 __is_nothrow_swappable<_T2>>::value)
2392 { _Inherited::_M_swap(__in); }
2394 #endif // concepts && conditional_explicit
2396 /// class tuple_size
2397 template<typename... _Elements>
2398 struct tuple_size<tuple<_Elements...>>
2399 : public integral_constant<size_t, sizeof...(_Elements)> { };
2401 #if __cplusplus >= 201703L
2402 template<typename... _Types>
2403 inline constexpr size_t tuple_size_v<tuple<_Types...>>
2404 = sizeof...(_Types);
2406 template<typename... _Types>
2407 inline constexpr size_t tuple_size_v<const tuple<_Types...>>
2408 = sizeof...(_Types);
2411 /// Trait to get the Ith element type from a tuple.
2412 template<size_t __i, typename... _Types>
2413 struct tuple_element<__i, tuple<_Types...>>
2415 static_assert(__i < sizeof...(_Types), "tuple index must be in range");
2417 using type = typename _Nth_type<__i, _Types...>::type;
2420 template<size_t __i, typename _Head, typename... _Tail>
2422 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2423 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2425 template<size_t __i, typename _Head, typename... _Tail>
2426 constexpr const _Head&
2427 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2428 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2430 // Deleted overload to improve diagnostics for invalid indices
2431 template<size_t __i, typename... _Types>
2432 __enable_if_t<(__i >= sizeof...(_Types))>
2433 __get_helper(const tuple<_Types...>&) = delete;
2435 /// Return a reference to the ith element of a tuple.
2436 template<size_t __i, typename... _Elements>
2437 constexpr __tuple_element_t<__i, tuple<_Elements...>>&
2438 get(tuple<_Elements...>& __t) noexcept
2439 { return std::__get_helper<__i>(__t); }
2441 /// Return a const reference to the ith element of a const tuple.
2442 template<size_t __i, typename... _Elements>
2443 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
2444 get(const tuple<_Elements...>& __t) noexcept
2445 { return std::__get_helper<__i>(__t); }
2447 /// Return an rvalue reference to the ith element of a tuple rvalue.
2448 template<size_t __i, typename... _Elements>
2449 constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
2450 get(tuple<_Elements...>&& __t) noexcept
2452 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2453 return std::forward<__element_type>(std::__get_helper<__i>(__t));
2456 /// Return a const rvalue reference to the ith element of a const tuple rvalue.
2457 template<size_t __i, typename... _Elements>
2458 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
2459 get(const tuple<_Elements...>&& __t) noexcept
2461 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2462 return std::forward<const __element_type>(std::__get_helper<__i>(__t));
2465 /// @cond undocumented
2466 // Deleted overload chosen for invalid indices.
2467 template<size_t __i, typename... _Elements>
2468 constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
2469 get(const tuple<_Elements...>&) = delete;
2472 #ifdef __cpp_lib_tuples_by_type // C++ >= 14
2473 /// Return a reference to the unique element of type _Tp of a tuple.
2474 template <typename _Tp, typename... _Types>
2476 get(tuple<_Types...>& __t) noexcept
2478 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2479 static_assert(__idx < sizeof...(_Types),
2480 "the type T in std::get<T> must occur exactly once in the tuple");
2481 return std::__get_helper<__idx>(__t);
2484 /// Return a reference to the unique element of type _Tp of a tuple rvalue.
2485 template <typename _Tp, typename... _Types>
2487 get(tuple<_Types...>&& __t) noexcept
2489 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2490 static_assert(__idx < sizeof...(_Types),
2491 "the type T in std::get<T> must occur exactly once in the tuple");
2492 return std::forward<_Tp>(std::__get_helper<__idx>(__t));
2495 /// Return a const reference to the unique element of type _Tp of a tuple.
2496 template <typename _Tp, typename... _Types>
2497 constexpr const _Tp&
2498 get(const tuple<_Types...>& __t) noexcept
2500 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2501 static_assert(__idx < sizeof...(_Types),
2502 "the type T in std::get<T> must occur exactly once in the tuple");
2503 return std::__get_helper<__idx>(__t);
2506 /// Return a const reference to the unique element of type _Tp of
2507 /// a const tuple rvalue.
2508 template <typename _Tp, typename... _Types>
2509 constexpr const _Tp&&
2510 get(const tuple<_Types...>&& __t) noexcept
2512 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2513 static_assert(__idx < sizeof...(_Types),
2514 "the type T in std::get<T> must occur exactly once in the tuple");
2515 return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
2519 #if __cpp_lib_three_way_comparison
2520 template<typename... _Tps, typename... _Ups>
2521 requires (sizeof...(_Tps) == sizeof...(_Ups))
2522 && (requires (const _Tps& __t, const _Ups& __u) {
2523 { __t == __u } -> __detail::__boolean_testable;
2526 operator== [[nodiscard]] (const tuple<_Tps...>& __t,
2527 const tuple<_Ups...>& __u)
2529 return [&]<size_t... _Inds>(index_sequence<_Inds...>) {
2530 // Fold == over the tuples until non-equal elements are found.
2531 return ((std::get<_Inds>(__t) == std::get<_Inds>(__u)) && ...);
2532 }(index_sequence_for<_Tps...>{});
2535 template<typename _Cat, typename _Tp, typename _Up, typename _IndexSeq>
2538 __tuple_cmp(const _Tp& __t, const _Up& __u, _IndexSeq __indices)
2540 _Cat __c = _Cat::equivalent;
2542 // Set __c to the comparison result of two corresponding elements.
2543 // Return true they are equivalent.
2544 auto __cmp = [&]<size_t _Ind>(integral_constant<size_t, _Ind>) {
2545 __c = __detail::__synth3way(std::get<_Ind>(__t), std::get<_Ind>(__u));
2549 [&]<size_t... _Inds>(index_sequence<_Inds...>) {
2550 // Fold __cmp over the tuples until non-equivalent elements are found.
2551 (void)(__cmp(integral_constant<size_t, _Inds>{}) && ...);
2557 template<typename... _Tps, typename... _Ups>
2558 requires (sizeof...(_Tps) == sizeof...(_Ups))
2559 && (requires { typename __detail::__synth3way_t<_Tps, _Ups>; } && ...)
2561 common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
2562 operator<=> [[nodiscard]] (const tuple<_Tps...>& __t,
2563 const tuple<_Ups...>& __u)
2566 = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
2567 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
2571 // This class performs the comparison operations on tuples
2572 template<typename _Tp, typename _Up, size_t __i, size_t __size>
2573 struct __tuple_compare
2575 static constexpr bool
2576 __eq(const _Tp& __t, const _Up& __u)
2578 return bool(std::get<__i>(__t) == std::get<__i>(__u))
2579 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
2582 static constexpr bool
2583 __less(const _Tp& __t, const _Up& __u)
2585 return bool(std::get<__i>(__t) < std::get<__i>(__u))
2586 || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
2587 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
2591 template<typename _Tp, typename _Up, size_t __size>
2592 struct __tuple_compare<_Tp, _Up, __size, __size>
2594 static constexpr bool
2595 __eq(const _Tp&, const _Up&) { return true; }
2597 static constexpr bool
2598 __less(const _Tp&, const _Up&) { return false; }
2601 template<typename... _TElements, typename... _UElements>
2604 operator==(const tuple<_TElements...>& __t,
2605 const tuple<_UElements...>& __u)
2607 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2608 "tuple objects can only be compared if they have equal sizes.");
2609 using __compare = __tuple_compare<tuple<_TElements...>,
2610 tuple<_UElements...>,
2611 0, sizeof...(_TElements)>;
2612 return __compare::__eq(__t, __u);
2615 template<typename... _TElements, typename... _UElements>
2618 operator<(const tuple<_TElements...>& __t,
2619 const tuple<_UElements...>& __u)
2621 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2622 "tuple objects can only be compared if they have equal sizes.");
2623 using __compare = __tuple_compare<tuple<_TElements...>,
2624 tuple<_UElements...>,
2625 0, sizeof...(_TElements)>;
2626 return __compare::__less(__t, __u);
2629 template<typename... _TElements, typename... _UElements>
2632 operator!=(const tuple<_TElements...>& __t,
2633 const tuple<_UElements...>& __u)
2634 { return !(__t == __u); }
2636 template<typename... _TElements, typename... _UElements>
2639 operator>(const tuple<_TElements...>& __t,
2640 const tuple<_UElements...>& __u)
2641 { return __u < __t; }
2643 template<typename... _TElements, typename... _UElements>
2646 operator<=(const tuple<_TElements...>& __t,
2647 const tuple<_UElements...>& __u)
2648 { return !(__u < __t); }
2650 template<typename... _TElements, typename... _UElements>
2653 operator>=(const tuple<_TElements...>& __t,
2654 const tuple<_UElements...>& __u)
2655 { return !(__t < __u); }
2656 #endif // three_way_comparison
2659 /// Create a tuple containing copies of the arguments
2660 template<typename... _Elements>
2661 constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
2662 make_tuple(_Elements&&... __args)
2664 typedef tuple<typename __decay_and_strip<_Elements>::__type...>
2666 return __result_type(std::forward<_Elements>(__args)...);
2669 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2670 // 2275. Why is forward_as_tuple not constexpr?
2671 /// Create a tuple of lvalue or rvalue references to the arguments
2672 template<typename... _Elements>
2673 constexpr tuple<_Elements&&...>
2674 forward_as_tuple(_Elements&&... __args) noexcept
2675 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2677 /// @cond undocumented
2678 template<size_t, typename, typename, size_t>
2679 struct __make_tuple_impl;
2681 template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
2682 struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
2683 : __make_tuple_impl<_Idx + 1,
2684 tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
2688 template<size_t _Nm, typename _Tuple, typename... _Tp>
2689 struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
2691 typedef tuple<_Tp...> __type;
2694 template<typename _Tuple>
2695 struct __do_make_tuple
2696 : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
2699 // Returns the std::tuple equivalent of a tuple-like type.
2700 template<typename _Tuple>
2702 : public __do_make_tuple<__remove_cvref_t<_Tuple>>
2705 // Combines several std::tuple's into a single one.
2706 template<typename...>
2707 struct __combine_tuples;
2710 struct __combine_tuples<>
2712 typedef tuple<> __type;
2715 template<typename... _Ts>
2716 struct __combine_tuples<tuple<_Ts...>>
2718 typedef tuple<_Ts...> __type;
2721 template<typename... _T1s, typename... _T2s, typename... _Rem>
2722 struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
2724 typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
2725 _Rem...>::__type __type;
2728 // Computes the result type of tuple_cat given a set of tuple-like types.
2729 template<typename... _Tpls>
2730 struct __tuple_cat_result
2732 typedef typename __combine_tuples
2733 <typename __make_tuple<_Tpls>::__type...>::__type __type;
2736 // Helper to determine the index set for the first tuple-like
2737 // type of a given set.
2738 template<typename...>
2739 struct __make_1st_indices;
2742 struct __make_1st_indices<>
2744 typedef _Index_tuple<> __type;
2747 template<typename _Tp, typename... _Tpls>
2748 struct __make_1st_indices<_Tp, _Tpls...>
2750 typedef typename _Build_index_tuple<tuple_size<
2751 typename remove_reference<_Tp>::type>::value>::__type __type;
2754 // Performs the actual concatenation by step-wise expanding tuple-like
2755 // objects into the elements, which are finally forwarded into the
2757 template<typename _Ret, typename _Indices, typename... _Tpls>
2758 struct __tuple_concater;
2760 template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2761 struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2763 template<typename... _Us>
2764 static constexpr _Ret
2765 _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2767 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2768 typedef __tuple_concater<_Ret, __idx, _Tpls...> __next;
2769 return __next::_S_do(std::forward<_Tpls>(__tps)...,
2770 std::forward<_Us>(__us)...,
2771 std::get<_Is>(std::forward<_Tp>(__tp))...);
2775 template<typename _Ret>
2776 struct __tuple_concater<_Ret, _Index_tuple<>>
2778 template<typename... _Us>
2779 static constexpr _Ret
2780 _S_do(_Us&&... __us)
2782 return _Ret(std::forward<_Us>(__us)...);
2786 template<typename... _Tps>
2787 struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2791 /// Create a `tuple` containing all elements from multiple tuple-like objects
2792 #if __cpp_lib_tuple_like // >= C++23
2793 template<__tuple_like... _Tpls>
2795 template<typename... _Tpls, typename = typename
2796 enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2799 tuple_cat(_Tpls&&... __tpls)
2800 -> typename __tuple_cat_result<_Tpls...>::__type
2802 typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2803 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2804 typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2805 return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2808 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2809 // 2301. Why is tie not constexpr?
2810 /// Return a tuple of lvalue references bound to the arguments
2811 template<typename... _Elements>
2812 constexpr tuple<_Elements&...>
2813 tie(_Elements&... __args) noexcept
2814 { return tuple<_Elements&...>(__args...); }
2816 /// Exchange the values of two tuples
2817 template<typename... _Elements>
2818 _GLIBCXX20_CONSTEXPR
2820 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2821 // Constrained free swap overload, see p0185r1
2822 typename enable_if<__and_<__is_swappable<_Elements>...>::value
2827 swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
2828 noexcept(noexcept(__x.swap(__y)))
2831 #if __cpp_lib_ranges_zip // >= C++23
2832 template<typename... _Elements>
2833 requires (is_swappable_v<const _Elements> && ...)
2835 swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2836 noexcept(noexcept(__x.swap(__y)))
2840 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2841 /// Exchange the values of two const tuples (if const elements can be swapped)
2842 template<typename... _Elements>
2843 _GLIBCXX20_CONSTEXPR
2844 typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2845 swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2848 /// Partial specialization for tuples
2849 template<typename... _Types, typename _Alloc>
2850 struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2852 // See stl_pair.h...
2853 /** "piecewise construction" using a tuple of arguments for each member.
2855 * @param __first Arguments for the first member of the pair.
2856 * @param __second Arguments for the second member of the pair.
2858 * The elements of each tuple will be used as the constructor arguments
2859 * for the data members of the pair.
2861 template<class _T1, class _T2>
2862 template<typename... _Args1, typename... _Args2>
2863 _GLIBCXX20_CONSTEXPR
2866 pair(piecewise_construct_t,
2867 tuple<_Args1...> __first, tuple<_Args2...> __second)
2868 : pair(__first, __second,
2869 typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2870 typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2873 template<class _T1, class _T2>
2874 template<typename... _Args1, size_t... _Indexes1,
2875 typename... _Args2, size_t... _Indexes2>
2876 _GLIBCXX20_CONSTEXPR inline
2878 pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2879 _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2880 : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2881 second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2884 #if defined(__cpp_lib_apply) || defined(__cpp_lib_make_from_tuple) // C++ >= 17
2885 // Unpack a std::tuple into a type trait and use its value.
2886 // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2887 // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2888 // Otherwise the result is false (because we don't know if std::get throws).
2889 template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2890 inline constexpr bool __unpack_std_tuple = false;
2892 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2893 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2894 = _Trait<_Tp, _Up...>::value;
2896 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2897 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2898 = _Trait<_Tp, _Up&...>::value;
2900 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2901 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2902 = _Trait<_Tp, const _Up...>::value;
2904 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2905 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2906 = _Trait<_Tp, const _Up&...>::value;
2909 #ifdef __cpp_lib_apply // C++ >= 17
2910 template <typename _Fn, typename _Tuple, size_t... _Idx>
2911 constexpr decltype(auto)
2912 __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2914 return std::__invoke(std::forward<_Fn>(__f),
2915 std::get<_Idx>(std::forward<_Tuple>(__t))...);
2918 #if __cpp_lib_tuple_like // >= C++23
2919 template <typename _Fn, __tuple_like _Tuple>
2921 template <typename _Fn, typename _Tuple>
2923 constexpr decltype(auto)
2924 apply(_Fn&& __f, _Tuple&& __t)
2925 noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2928 = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2929 return std::__apply_impl(std::forward<_Fn>(__f),
2930 std::forward<_Tuple>(__t),
2935 #ifdef __cpp_lib_make_from_tuple // C++ >= 17
2936 template <typename _Tp, typename _Tuple, size_t... _Idx>
2938 __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
2939 { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
2941 #if __cpp_lib_tuple_like // >= C++23
2942 template <typename _Tp, __tuple_like _Tuple>
2944 template <typename _Tp, typename _Tuple>
2947 make_from_tuple(_Tuple&& __t)
2948 noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
2950 constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
2951 #if __has_builtin(__reference_constructs_from_temporary)
2952 if constexpr (__n == 1)
2954 using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
2955 static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
2958 return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
2959 make_index_sequence<__n>{});
2963 #if __cpp_lib_tuple_like // >= C++23
2964 template<__tuple_like _TTuple, __tuple_like _UTuple,
2965 template<typename> class _TQual, template<typename> class _UQual,
2966 typename = make_index_sequence<tuple_size_v<_TTuple>>>
2967 struct __tuple_like_common_reference;
2969 template<__tuple_like _TTuple, __tuple_like _UTuple,
2970 template<typename> class _TQual, template<typename> class _UQual,
2973 { typename tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2974 _UQual<tuple_element_t<_Is, _UTuple>>>...>; }
2975 struct __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual, index_sequence<_Is...>>
2977 using type = tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2978 _UQual<tuple_element_t<_Is, _UTuple>>>...>;
2981 template<__tuple_like _TTuple, __tuple_like _UTuple,
2982 template<typename> class _TQual, template<typename> class _UQual>
2983 requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
2984 && is_same_v<_TTuple, decay_t<_TTuple>>
2985 && is_same_v<_UTuple, decay_t<_UTuple>>
2986 && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
2987 && requires { typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type; }
2988 struct basic_common_reference<_TTuple, _UTuple, _TQual, _UQual>
2990 using type = typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type;
2993 template<__tuple_like _TTuple, __tuple_like _UTuple,
2994 typename = make_index_sequence<tuple_size_v<_TTuple>>>
2995 struct __tuple_like_common_type;
2997 template<__tuple_like _TTuple, __tuple_like _UTuple, size_t... _Is>
2999 { typename tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3000 tuple_element_t<_Is, _UTuple>>...>; }
3001 struct __tuple_like_common_type<_TTuple, _UTuple, index_sequence<_Is...>>
3003 using type = tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3004 tuple_element_t<_Is, _UTuple>>...>;
3007 template<__tuple_like _TTuple, __tuple_like _UTuple>
3008 requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
3009 && is_same_v<_TTuple, decay_t<_TTuple>>
3010 && is_same_v<_UTuple, decay_t<_UTuple>>
3011 && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
3012 && requires { typename __tuple_like_common_type<_TTuple, _UTuple>::type; }
3013 struct common_type<_TTuple, _UTuple>
3015 using type = typename __tuple_like_common_type<_TTuple, _UTuple>::type;
3021 #undef __glibcxx_no_dangling_refs
3023 _GLIBCXX_END_NAMESPACE_VERSION
3028 #endif // _GLIBCXX_TUPLE