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 #include <bits/version.h>
56 namespace std _GLIBCXX_VISIBILITY(default)
58 _GLIBCXX_BEGIN_NAMESPACE_VERSION
61 * @addtogroup utilities
65 template<typename... _Elements>
68 template<typename _Tp>
69 struct __is_empty_non_tuple : is_empty<_Tp> { };
71 // Using EBO for elements that are tuples causes ambiguous base errors.
72 template<typename _El0, typename... _El>
73 struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { };
75 // Use the Empty Base-class Optimization for empty, non-final types.
76 template<typename _Tp>
77 using __empty_not_final
78 = __conditional_t<__is_final(_Tp), false_type,
79 __is_empty_non_tuple<_Tp>>;
81 template<size_t _Idx, typename _Head,
82 bool = __empty_not_final<_Head>::value>
85 #if __has_cpp_attribute(__no_unique_address__)
86 template<size_t _Idx, typename _Head>
87 struct _Head_base<_Idx, _Head, true>
89 constexpr _Head_base()
92 constexpr _Head_base(const _Head& __h)
93 : _M_head_impl(__h) { }
95 constexpr _Head_base(const _Head_base&) = default;
96 constexpr _Head_base(_Head_base&&) = default;
98 template<typename _UHead>
99 constexpr _Head_base(_UHead&& __h)
100 : _M_head_impl(std::forward<_UHead>(__h)) { }
103 _Head_base(allocator_arg_t, __uses_alloc0)
106 template<typename _Alloc>
108 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
109 : _M_head_impl(allocator_arg, *__a._M_a) { }
111 template<typename _Alloc>
113 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
114 : _M_head_impl(*__a._M_a) { }
116 template<typename _UHead>
118 _Head_base(__uses_alloc0, _UHead&& __uhead)
119 : _M_head_impl(std::forward<_UHead>(__uhead)) { }
121 template<typename _Alloc, typename _UHead>
123 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
124 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
127 template<typename _Alloc, typename _UHead>
129 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
130 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
132 static constexpr _Head&
133 _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
135 static constexpr const _Head&
136 _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
138 [[__no_unique_address__]] _Head _M_head_impl;
141 template<size_t _Idx, typename _Head>
142 struct _Head_base<_Idx, _Head, true>
145 constexpr _Head_base()
148 constexpr _Head_base(const _Head& __h)
151 constexpr _Head_base(const _Head_base&) = default;
152 constexpr _Head_base(_Head_base&&) = default;
154 template<typename _UHead>
155 constexpr _Head_base(_UHead&& __h)
156 : _Head(std::forward<_UHead>(__h)) { }
159 _Head_base(allocator_arg_t, __uses_alloc0)
162 template<typename _Alloc>
164 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
165 : _Head(allocator_arg, *__a._M_a) { }
167 template<typename _Alloc>
169 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
170 : _Head(*__a._M_a) { }
172 template<typename _UHead>
174 _Head_base(__uses_alloc0, _UHead&& __uhead)
175 : _Head(std::forward<_UHead>(__uhead)) { }
177 template<typename _Alloc, typename _UHead>
179 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
180 : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
182 template<typename _Alloc, typename _UHead>
184 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
185 : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
187 static constexpr _Head&
188 _M_head(_Head_base& __b) noexcept { return __b; }
190 static constexpr const _Head&
191 _M_head(const _Head_base& __b) noexcept { return __b; }
195 template<size_t _Idx, typename _Head>
196 struct _Head_base<_Idx, _Head, false>
198 constexpr _Head_base()
201 constexpr _Head_base(const _Head& __h)
202 : _M_head_impl(__h) { }
204 constexpr _Head_base(const _Head_base&) = default;
205 constexpr _Head_base(_Head_base&&) = default;
207 template<typename _UHead>
208 constexpr _Head_base(_UHead&& __h)
209 : _M_head_impl(std::forward<_UHead>(__h)) { }
212 _Head_base(allocator_arg_t, __uses_alloc0)
215 template<typename _Alloc>
217 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
218 : _M_head_impl(allocator_arg, *__a._M_a) { }
220 template<typename _Alloc>
222 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
223 : _M_head_impl(*__a._M_a) { }
225 template<typename _UHead>
227 _Head_base(__uses_alloc0, _UHead&& __uhead)
228 : _M_head_impl(std::forward<_UHead>(__uhead)) { }
230 template<typename _Alloc, typename _UHead>
232 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
233 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
236 template<typename _Alloc, typename _UHead>
238 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
239 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
241 static constexpr _Head&
242 _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
244 static constexpr const _Head&
245 _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
250 #if __cpp_lib_tuple_like // >= C++23
251 struct __tuple_like_tag_t { explicit __tuple_like_tag_t() = default; };
253 // These forward declarations are used by the operator<=> overload for
255 template<typename _Cat, typename _Tp, typename _Up>
257 __tuple_cmp(const _Tp&, const _Up&, index_sequence<>);
259 template<typename _Cat, typename _Tp, typename _Up,
260 size_t _Idx0, size_t... _Idxs>
262 __tuple_cmp(const _Tp& __t, const _Up& __u,
263 index_sequence<_Idx0, _Idxs...>);
267 * Contains the actual implementation of the @c tuple template, stored
268 * as a recursive inheritance hierarchy from the first element (most
269 * derived class) to the last (least derived class). The @c Idx
270 * parameter gives the 0-based index of the element stored at this
271 * point in the hierarchy; we use it to implement a constant-time
274 template<size_t _Idx, typename... _Elements>
278 * Recursive tuple implementation. Here we store the @c Head element
279 * and derive from a @c Tuple_impl containing the remaining elements
280 * (which contains the @c Tail).
282 template<size_t _Idx, typename _Head, typename... _Tail>
283 struct _Tuple_impl<_Idx, _Head, _Tail...>
284 : public _Tuple_impl<_Idx + 1, _Tail...>,
285 private _Head_base<_Idx, _Head>
287 template<size_t, typename...> friend struct _Tuple_impl;
289 typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
290 typedef _Head_base<_Idx, _Head> _Base;
292 static constexpr _Head&
293 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
295 static constexpr const _Head&
296 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
298 static constexpr _Inherited&
299 _M_tail(_Tuple_impl& __t) noexcept { return __t; }
301 static constexpr const _Inherited&
302 _M_tail(const _Tuple_impl& __t) noexcept { return __t; }
304 constexpr _Tuple_impl()
305 : _Inherited(), _Base() { }
308 _Tuple_impl(const _Head& __head, const _Tail&... __tail)
309 : _Inherited(__tail...), _Base(__head)
312 template<typename _UHead, typename... _UTail,
313 typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
315 _Tuple_impl(_UHead&& __head, _UTail&&... __tail)
316 : _Inherited(std::forward<_UTail>(__tail)...),
317 _Base(std::forward<_UHead>(__head))
320 constexpr _Tuple_impl(const _Tuple_impl&) = default;
322 // _GLIBCXX_RESOLVE_LIB_DEFECTS
323 // 2729. Missing SFINAE on std::pair::operator=
324 _Tuple_impl& operator=(const _Tuple_impl&) = delete;
326 _Tuple_impl(_Tuple_impl&&) = default;
328 template<typename... _UElements>
330 _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
331 : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
332 _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
335 template<typename _UHead, typename... _UTails>
337 _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
338 : _Inherited(std::move
339 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
340 _Base(std::forward<_UHead>
341 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
344 #if __cpp_lib_ranges_zip // >= C++23
345 template<typename... _UElements>
347 _Tuple_impl(_Tuple_impl<_Idx, _UElements...>& __in)
348 : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
349 _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
352 template<typename _UHead, typename... _UTails>
354 _Tuple_impl(const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
355 : _Inherited(std::move
356 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
357 _Base(std::forward<const _UHead>
358 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
362 #if __cpp_lib_tuple_like // >= C++23
363 template<typename _UTuple, size_t... _Is>
365 _Tuple_impl(__tuple_like_tag_t, _UTuple&& __u, index_sequence<_Is...>)
366 : _Tuple_impl(std::get<_Is>(std::forward<_UTuple>(__u))...)
370 template<typename _Alloc>
372 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
373 : _Inherited(__tag, __a),
374 _Base(__tag, __use_alloc<_Head>(__a))
377 template<typename _Alloc>
379 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
380 const _Head& __head, const _Tail&... __tail)
381 : _Inherited(__tag, __a, __tail...),
382 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head)
385 template<typename _Alloc, typename _UHead, typename... _UTail,
386 typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
388 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
389 _UHead&& __head, _UTail&&... __tail)
390 : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
391 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
392 std::forward<_UHead>(__head))
395 template<typename _Alloc>
397 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
398 const _Tuple_impl& __in)
399 : _Inherited(__tag, __a, _M_tail(__in)),
400 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in))
403 template<typename _Alloc>
405 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
407 : _Inherited(__tag, __a, std::move(_M_tail(__in))),
408 _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
409 std::forward<_Head>(_M_head(__in)))
412 template<typename _Alloc, typename _UHead, typename... _UTails>
414 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
415 const _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
416 : _Inherited(__tag, __a,
417 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
418 _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
419 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
422 template<typename _Alloc, typename _UHead, typename... _UTails>
424 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
425 _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
426 : _Inherited(__tag, __a, std::move
427 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
428 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
430 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
433 #if __cpp_lib_ranges_zip // >= C++23
434 template<typename _Alloc, typename _UHead, typename... _UTails>
436 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
437 _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
438 : _Inherited(__tag, __a,
439 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
440 _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
441 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
444 template<typename _Alloc, typename _UHead, typename... _UTails>
446 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
447 const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
448 : _Inherited(__tag, __a, std::move
449 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
450 _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
451 std::forward<const _UHead>
452 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
456 #if __cpp_lib_tuple_like // >= C++23
457 template<typename _Alloc, typename _UTuple, size_t... _Is>
459 _Tuple_impl(__tuple_like_tag_t, allocator_arg_t __tag, const _Alloc& __a,
460 _UTuple&& __u, index_sequence<_Is...>)
461 : _Tuple_impl(__tag, __a, std::get<_Is>(std::forward<_UTuple>(__u))...)
465 template<typename... _UElements>
468 _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in)
470 _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
471 _M_tail(*this)._M_assign(
472 _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
475 template<typename _UHead, typename... _UTails>
478 _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
480 _M_head(*this) = std::forward<_UHead>
481 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
482 _M_tail(*this)._M_assign(
483 std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
486 #if __cpp_lib_ranges_zip // >= C++23
487 template<typename... _UElements>
489 _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) const
491 _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
492 _M_tail(*this)._M_assign(
493 _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
496 template<typename _UHead, typename... _UTails>
498 _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) const
500 _M_head(*this) = std::forward<_UHead>
501 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
502 _M_tail(*this)._M_assign(
503 std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
507 #if __cpp_lib_tuple_like // >= C++23
508 template<typename _UTuple>
510 _M_assign(__tuple_like_tag_t __tag, _UTuple&& __u)
512 _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u));
513 _M_tail(*this)._M_assign(__tag, std::forward<_UTuple>(__u));
516 template<typename _UTuple>
518 _M_assign(__tuple_like_tag_t __tag, _UTuple&& __u) const
520 _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u));
521 _M_tail(*this)._M_assign(__tag, std::forward<_UTuple>(__u));
528 _M_swap(_Tuple_impl& __in)
531 swap(_M_head(*this), _M_head(__in));
532 _Inherited::_M_swap(_M_tail(__in));
535 #if __cpp_lib_ranges_zip // >= C++23
537 _M_swap(const _Tuple_impl& __in) const
540 swap(_M_head(*this), _M_head(__in));
541 _Inherited::_M_swap(_M_tail(__in));
546 // Basis case of inheritance recursion.
547 template<size_t _Idx, typename _Head>
548 struct _Tuple_impl<_Idx, _Head>
549 : private _Head_base<_Idx, _Head>
551 template<size_t, typename...> friend struct _Tuple_impl;
553 typedef _Head_base<_Idx, _Head> _Base;
555 static constexpr _Head&
556 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
558 static constexpr const _Head&
559 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
566 _Tuple_impl(const _Head& __head)
570 template<typename _UHead>
572 _Tuple_impl(_UHead&& __head)
573 : _Base(std::forward<_UHead>(__head))
576 constexpr _Tuple_impl(const _Tuple_impl&) = default;
578 // _GLIBCXX_RESOLVE_LIB_DEFECTS
579 // 2729. Missing SFINAE on std::pair::operator=
580 _Tuple_impl& operator=(const _Tuple_impl&) = delete;
582 #if _GLIBCXX_INLINE_VERSION
583 _Tuple_impl(_Tuple_impl&&) = default;
586 _Tuple_impl(_Tuple_impl&& __in)
587 noexcept(is_nothrow_move_constructible<_Head>::value)
588 : _Base(static_cast<_Base&&>(__in))
592 template<typename _UHead>
594 _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in)
595 : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
598 template<typename _UHead>
600 _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in)
601 : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
604 #if __cpp_lib_ranges_zip // >= C++23
605 template<typename _UHead>
607 _Tuple_impl(_Tuple_impl<_Idx, _UHead>& __in)
608 : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
611 template<typename _UHead>
613 _Tuple_impl(const _Tuple_impl<_Idx, _UHead>&& __in)
614 : _Base(std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
618 #if __cpp_lib_tuple_like // >= C++23
619 template<typename _UTuple>
621 _Tuple_impl(__tuple_like_tag_t, _UTuple&& __u, index_sequence<0>)
622 : _Tuple_impl(std::get<0>(std::forward<_UTuple>(__u)))
626 template<typename _Alloc>
628 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
629 : _Base(__tag, __use_alloc<_Head>(__a))
632 template<typename _Alloc>
634 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
636 : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), __head)
639 template<typename _Alloc, typename _UHead>
641 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
643 : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
644 std::forward<_UHead>(__head))
647 template<typename _Alloc>
649 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
650 const _Tuple_impl& __in)
651 : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), _M_head(__in))
654 template<typename _Alloc>
656 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
658 : _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
659 std::forward<_Head>(_M_head(__in)))
662 template<typename _Alloc, typename _UHead>
664 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
665 const _Tuple_impl<_Idx, _UHead>& __in)
666 : _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
667 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
670 template<typename _Alloc, typename _UHead>
672 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
673 _Tuple_impl<_Idx, _UHead>&& __in)
674 : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
675 std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
678 #if __cpp_lib_ranges_zip // >= C++23
679 template<typename _Alloc, typename _UHead>
681 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
682 _Tuple_impl<_Idx, _UHead>& __in)
683 : _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
684 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
687 template<typename _Alloc, typename _UHead>
689 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
690 const _Tuple_impl<_Idx, _UHead>&& __in)
691 : _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
692 std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
696 #if __cpp_lib_tuple_like // >= C++23
697 template<typename _Alloc, typename _UTuple>
699 _Tuple_impl(__tuple_like_tag_t, allocator_arg_t __tag, const _Alloc& __a,
700 _UTuple&& __u, index_sequence<0>)
701 : _Tuple_impl(__tag, __a, std::get<0>(std::forward<_UTuple>(__u)))
705 template<typename _UHead>
708 _M_assign(const _Tuple_impl<_Idx, _UHead>& __in)
710 _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
713 template<typename _UHead>
716 _M_assign(_Tuple_impl<_Idx, _UHead>&& __in)
719 = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
722 #if __cpp_lib_ranges_zip // >= C++23
723 template<typename _UHead>
725 _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) const
727 _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
730 template<typename _UHead>
732 _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) const
735 = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
739 #if __cpp_lib_tuple_like // >= C++23
740 template<typename _UTuple>
742 _M_assign(__tuple_like_tag_t, _UTuple&& __u)
743 { _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); }
745 template<typename _UTuple>
747 _M_assign(__tuple_like_tag_t, _UTuple&& __u) const
748 { _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); }
754 _M_swap(_Tuple_impl& __in)
757 swap(_M_head(*this), _M_head(__in));
760 #if __cpp_lib_ranges_zip // >= C++23
762 _M_swap(const _Tuple_impl& __in) const
765 swap(_M_head(*this), _M_head(__in));
770 // Concept utility functions, reused in conditionally-explicit
772 template<bool, typename... _Types>
773 struct _TupleConstraints
775 template<typename... _UTypes>
776 using __constructible = __and_<is_constructible<_Types, _UTypes>...>;
778 template<typename... _UTypes>
779 using __convertible = __and_<is_convertible<_UTypes, _Types>...>;
781 // Constraint for a non-explicit constructor.
782 // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
783 // and every Ui is implicitly convertible to Ti.
784 template<typename... _UTypes>
785 static constexpr bool __is_implicitly_constructible()
787 return __and_<__constructible<_UTypes...>,
788 __convertible<_UTypes...>
792 // Constraint for a non-explicit constructor.
793 // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
794 // but not every Ui is implicitly convertible to Ti.
795 template<typename... _UTypes>
796 static constexpr bool __is_explicitly_constructible()
798 return __and_<__constructible<_UTypes...>,
799 __not_<__convertible<_UTypes...>>
803 static constexpr bool __is_implicitly_default_constructible()
805 return __and_<std::__is_implicitly_default_constructible<_Types>...
809 static constexpr bool __is_explicitly_default_constructible()
811 return __and_<is_default_constructible<_Types>...,
813 std::__is_implicitly_default_constructible<_Types>...>
818 // Partial specialization used when a required precondition isn't met,
819 // e.g. when sizeof...(_Types) != sizeof...(_UTypes).
820 template<typename... _Types>
821 struct _TupleConstraints<false, _Types...>
823 template<typename... _UTypes>
824 static constexpr bool __is_implicitly_constructible()
827 template<typename... _UTypes>
828 static constexpr bool __is_explicitly_constructible()
832 /// Primary class template, tuple
833 template<typename... _Elements>
834 class tuple : public _Tuple_impl<0, _Elements...>
836 using _Inherited = _Tuple_impl<0, _Elements...>;
838 #if __cpp_concepts && __cpp_consteval && __cpp_conditional_explicit // >= C++20
839 template<typename... _UTypes>
840 static consteval bool
843 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
844 return __and_v<is_constructible<_Elements, _UTypes>...>;
849 template<typename... _UTypes>
850 static consteval bool
851 __nothrow_constructible()
853 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
854 return __and_v<is_nothrow_constructible<_Elements, _UTypes>...>;
859 template<typename... _UTypes>
860 static consteval bool
863 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
864 return __and_v<is_convertible<_UTypes, _Elements>...>;
869 // _GLIBCXX_RESOLVE_LIB_DEFECTS
870 // 3121. tuple constructor constraints for UTypes&&... overloads
871 template<typename... _UTypes>
872 static consteval bool
873 __disambiguating_constraint()
875 if constexpr (sizeof...(_Elements) != sizeof...(_UTypes))
877 else if constexpr (sizeof...(_Elements) == 1)
879 using _U0 = typename _Nth_type<0, _UTypes...>::type;
880 return !is_same_v<remove_cvref_t<_U0>, tuple>;
882 else if constexpr (sizeof...(_Elements) < 4)
884 using _U0 = typename _Nth_type<0, _UTypes...>::type;
885 if constexpr (!is_same_v<remove_cvref_t<_U0>, allocator_arg_t>)
889 using _T0 = typename _Nth_type<0, _Elements...>::type;
890 return is_same_v<remove_cvref_t<_T0>, allocator_arg_t>;
896 // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
897 // and the single element in Types can be initialized from TUPLE,
898 // or is the same type as tuple_element_t<0, TUPLE>.
899 template<typename _Tuple>
900 static consteval bool
903 if constexpr (sizeof...(_Elements) != 1)
905 else if constexpr (is_same_v<remove_cvref_t<_Tuple>, tuple>)
906 return true; // Should use a copy/move constructor instead.
909 using _Tp = typename _Nth_type<0, _Elements...>::type;
910 if constexpr (is_convertible_v<_Tuple, _Tp>)
912 else if constexpr (is_constructible_v<_Tp, _Tuple>)
918 template<typename... _Up>
919 static consteval bool
922 #if __has_builtin(__reference_constructs_from_temporary)
923 return (__reference_constructs_from_temporary(_Elements, _Up&&)
930 #if __cpp_lib_tuple_like // >= C++23
931 // _GLIBCXX_RESOLVE_LIB_DEFECTS
932 // 4045. tuple can create dangling references from tuple-like
933 template<typename _UTuple>
934 static consteval bool
935 __dangles_from_tuple_like()
937 return []<size_t... _Is>(index_sequence<_Is...>) {
938 return __dangles<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
939 }(index_sequence_for<_Elements...>{});
942 template<typename _UTuple>
943 static consteval bool
944 __constructible_from_tuple_like()
946 return []<size_t... _Is>(index_sequence<_Is...>) {
947 return __constructible<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
948 }(index_sequence_for<_Elements...>{});
951 template<typename _UTuple>
952 static consteval bool
953 __convertible_from_tuple_like()
955 return []<size_t... _Is>(index_sequence<_Is...>) {
956 return __convertible<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
957 }(index_sequence_for<_Elements...>{});
963 explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
965 noexcept((is_nothrow_default_constructible_v<_Elements> && ...))
966 requires (is_default_constructible_v<_Elements> && ...)
970 constexpr explicit(!__convertible<const _Elements&...>())
971 tuple(const _Elements&... __elements)
972 noexcept(__nothrow_constructible<const _Elements&...>())
973 requires (__constructible<const _Elements&...>())
974 : _Inherited(__elements...)
977 template<typename... _UTypes>
978 requires (__disambiguating_constraint<_UTypes...>())
979 && (__constructible<_UTypes...>())
980 && (!__dangles<_UTypes...>())
981 constexpr explicit(!__convertible<_UTypes...>())
982 tuple(_UTypes&&... __u)
983 noexcept(__nothrow_constructible<_UTypes...>())
984 : _Inherited(std::forward<_UTypes>(__u)...)
987 template<typename... _UTypes>
988 requires (__disambiguating_constraint<_UTypes...>())
989 && (__constructible<_UTypes...>())
990 && (__dangles<_UTypes...>())
991 tuple(_UTypes&&...) = delete;
993 constexpr tuple(const tuple&) = default;
995 constexpr tuple(tuple&&) = default;
997 template<typename... _UTypes>
998 requires (__constructible<const _UTypes&...>())
999 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1000 && (!__dangles<const _UTypes&...>())
1001 constexpr explicit(!__convertible<const _UTypes&...>())
1002 tuple(const tuple<_UTypes...>& __u)
1003 noexcept(__nothrow_constructible<const _UTypes&...>())
1004 : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1007 template<typename... _UTypes>
1008 requires (__constructible<const _UTypes&...>())
1009 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1010 && (__dangles<const _UTypes&...>())
1011 tuple(const tuple<_UTypes...>&) = delete;
1013 template<typename... _UTypes>
1014 requires (__constructible<_UTypes...>())
1015 && (!__use_other_ctor<tuple<_UTypes...>>())
1016 && (!__dangles<_UTypes...>())
1017 constexpr explicit(!__convertible<_UTypes...>())
1018 tuple(tuple<_UTypes...>&& __u)
1019 noexcept(__nothrow_constructible<_UTypes...>())
1020 : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1023 template<typename... _UTypes>
1024 requires (__constructible<_UTypes...>())
1025 && (!__use_other_ctor<tuple<_UTypes...>>())
1026 && (__dangles<_UTypes...>())
1027 tuple(tuple<_UTypes...>&&) = delete;
1029 #if __cpp_lib_ranges_zip // >= C++23
1030 template<typename... _UTypes>
1031 requires (__constructible<_UTypes&...>())
1032 && (!__use_other_ctor<tuple<_UTypes...>&>())
1033 && (!__dangles<_UTypes&...>())
1034 constexpr explicit(!__convertible<_UTypes&...>())
1035 tuple(tuple<_UTypes...>& __u)
1036 noexcept(__nothrow_constructible<_UTypes&...>())
1037 : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1040 template<typename... _UTypes>
1041 requires (__constructible<_UTypes&...>())
1042 && (!__use_other_ctor<tuple<_UTypes...>&>())
1043 && (__dangles<_UTypes&...>())
1044 tuple(tuple<_UTypes...>&) = delete;
1046 template<typename... _UTypes>
1047 requires (__constructible<const _UTypes...>())
1048 && (!__use_other_ctor<const tuple<_UTypes...>>())
1049 && (!__dangles<const _UTypes...>())
1050 constexpr explicit(!__convertible<const _UTypes...>())
1051 tuple(const tuple<_UTypes...>&& __u)
1052 noexcept(__nothrow_constructible<const _UTypes...>())
1053 : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1056 template<typename... _UTypes>
1057 requires (__constructible<const _UTypes...>())
1058 && (!__use_other_ctor<const tuple<_UTypes...>>())
1059 && (__dangles<const _UTypes...>())
1060 tuple(const tuple<_UTypes...>&&) = delete;
1063 template<typename _U1, typename _U2>
1064 requires (sizeof...(_Elements) == 2)
1065 && (__constructible<const _U1&, const _U2&>())
1066 && (!__dangles<const _U1&, const _U2&>())
1067 constexpr explicit(!__convertible<const _U1&, const _U2&>())
1068 tuple(const pair<_U1, _U2>& __u)
1069 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1070 : _Inherited(__u.first, __u.second)
1073 template<typename _U1, typename _U2>
1074 requires (sizeof...(_Elements) == 2)
1075 && (__constructible<const _U1&, const _U2&>())
1076 && (__dangles<const _U1&, const _U2&>())
1077 tuple(const pair<_U1, _U2>&) = delete;
1079 template<typename _U1, typename _U2>
1080 requires (sizeof...(_Elements) == 2)
1081 && (__constructible<_U1, _U2>())
1082 && (!__dangles<_U1, _U2>())
1083 constexpr explicit(!__convertible<_U1, _U2>())
1084 tuple(pair<_U1, _U2>&& __u)
1085 noexcept(__nothrow_constructible<_U1, _U2>())
1086 : _Inherited(std::forward<_U1>(__u.first),
1087 std::forward<_U2>(__u.second))
1090 template<typename _U1, typename _U2>
1091 requires (sizeof...(_Elements) == 2)
1092 && (__constructible<_U1, _U2>())
1093 && (__dangles<_U1, _U2>())
1094 tuple(pair<_U1, _U2>&&) = delete;
1096 #if __cpp_lib_ranges_zip // >= C++23
1097 template<typename _U1, typename _U2>
1098 requires (sizeof...(_Elements) == 2)
1099 && (__constructible<_U1&, _U2&>())
1100 && (!__dangles<_U1&, _U2&>())
1101 constexpr explicit(!__convertible<_U1&, _U2&>())
1102 tuple(pair<_U1, _U2>& __u)
1103 noexcept(__nothrow_constructible<_U1&, _U2&>())
1104 : _Inherited(__u.first, __u.second)
1107 template<typename _U1, typename _U2>
1108 requires (sizeof...(_Elements) == 2)
1109 && (__constructible<_U1&, _U2&>())
1110 && (__dangles<_U1&, _U2&>())
1111 tuple(pair<_U1, _U2>&) = delete;
1113 template<typename _U1, typename _U2>
1114 requires (sizeof...(_Elements) == 2)
1115 && (__constructible<const _U1, const _U2>())
1116 && (!__dangles<const _U1, const _U2>())
1117 constexpr explicit(!__convertible<const _U1, const _U2>())
1118 tuple(const pair<_U1, _U2>&& __u)
1119 noexcept(__nothrow_constructible<const _U1, const _U2>())
1120 : _Inherited(std::forward<const _U1>(__u.first),
1121 std::forward<const _U2>(__u.second))
1124 template<typename _U1, typename _U2>
1125 requires (sizeof...(_Elements) == 2)
1126 && (__constructible<const _U1, const _U2>())
1127 && (__dangles<const _U1, const _U2>())
1128 tuple(const pair<_U1, _U2>&&) = delete;
1131 #if __cpp_lib_tuple_like // >= C++23
1132 template<__eligible_tuple_like<tuple> _UTuple>
1133 requires (__constructible_from_tuple_like<_UTuple>())
1134 && (!__use_other_ctor<_UTuple>())
1135 && (!__dangles_from_tuple_like<_UTuple>())
1136 constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
1137 tuple(_UTuple&& __u)
1138 : _Inherited(__tuple_like_tag_t{},
1139 std::forward<_UTuple>(__u),
1140 index_sequence_for<_Elements...>{})
1143 template<__eligible_tuple_like<tuple> _UTuple>
1144 requires (__constructible_from_tuple_like<_UTuple>())
1145 && (!__use_other_ctor<_UTuple>())
1146 && (__dangles_from_tuple_like<_UTuple>())
1147 tuple(_UTuple&&) = delete;
1150 // Allocator-extended constructors.
1152 template<typename _Alloc>
1154 explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
1155 tuple(allocator_arg_t __tag, const _Alloc& __a)
1156 requires (is_default_constructible_v<_Elements> && ...)
1157 : _Inherited(__tag, __a)
1160 template<typename _Alloc>
1161 constexpr explicit(!__convertible<const _Elements&...>())
1162 tuple(allocator_arg_t __tag, const _Alloc& __a,
1163 const _Elements&... __elements)
1164 requires (__constructible<const _Elements&...>())
1165 : _Inherited(__tag, __a, __elements...)
1168 template<typename _Alloc, typename... _UTypes>
1169 requires (__disambiguating_constraint<_UTypes...>())
1170 && (__constructible<_UTypes...>())
1171 && (!__dangles<_UTypes...>())
1172 constexpr explicit(!__convertible<_UTypes...>())
1173 tuple(allocator_arg_t __tag, const _Alloc& __a, _UTypes&&... __u)
1174 : _Inherited(__tag, __a, std::forward<_UTypes>(__u)...)
1177 template<typename _Alloc, typename... _UTypes>
1178 requires (__disambiguating_constraint<_UTypes...>())
1179 && (__constructible<_UTypes...>())
1180 && (__dangles<_UTypes...>())
1181 tuple(allocator_arg_t, const _Alloc&, _UTypes&&...) = delete;
1183 template<typename _Alloc>
1185 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __u)
1186 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__u))
1189 template<typename _Alloc>
1190 requires (__constructible<_Elements...>())
1192 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __u)
1193 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__u))
1196 template<typename _Alloc, typename... _UTypes>
1197 requires (__constructible<const _UTypes&...>())
1198 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1199 && (!__dangles<const _UTypes&...>())
1200 constexpr explicit(!__convertible<const _UTypes&...>())
1201 tuple(allocator_arg_t __tag, const _Alloc& __a,
1202 const tuple<_UTypes...>& __u)
1203 : _Inherited(__tag, __a,
1204 static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1207 template<typename _Alloc, typename... _UTypes>
1208 requires (__constructible<const _UTypes&...>())
1209 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1210 && (__dangles<const _UTypes&...>())
1211 tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&) = delete;
1213 template<typename _Alloc, typename... _UTypes>
1214 requires (__constructible<_UTypes...>())
1215 && (!__use_other_ctor<tuple<_UTypes...>>())
1216 && (!__dangles<_UTypes...>())
1217 constexpr explicit(!__use_other_ctor<tuple<_UTypes...>>())
1218 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>&& __u)
1219 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1222 template<typename _Alloc, typename... _UTypes>
1223 requires (__constructible<_UTypes...>())
1224 && (!__use_other_ctor<tuple<_UTypes...>>())
1225 && (__dangles<_UTypes...>())
1226 tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&&) = delete;
1228 #if __cpp_lib_ranges_zip // >= C++23
1229 template<typename _Alloc, typename... _UTypes>
1230 requires (__constructible<_UTypes&...>())
1231 && (!__use_other_ctor<tuple<_UTypes...>&>())
1232 && (!__dangles<_UTypes&...>())
1233 constexpr explicit(!__convertible<_UTypes&...>())
1234 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>& __u)
1235 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1238 template<typename _Alloc, typename... _UTypes>
1239 requires (__constructible<_UTypes&...>())
1240 && (!__use_other_ctor<tuple<_UTypes...>&>())
1241 && (__dangles<_UTypes&...>())
1242 tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&) = delete;
1244 template<typename _Alloc, typename... _UTypes>
1245 requires (__constructible<const _UTypes...>())
1246 && (!__use_other_ctor<const tuple<_UTypes...>>())
1247 && (!__dangles<const _UTypes...>())
1248 constexpr explicit(!__convertible<const _UTypes...>())
1249 tuple(allocator_arg_t __tag, const _Alloc& __a,
1250 const tuple<_UTypes...>&& __u)
1251 : _Inherited(__tag, __a,
1252 static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1255 template<typename _Alloc, typename... _UTypes>
1256 requires (__constructible<const _UTypes...>())
1257 && (!__use_other_ctor<const tuple<_UTypes...>>())
1258 && (__dangles<const _UTypes...>())
1259 tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&&) = delete;
1262 template<typename _Alloc, typename _U1, typename _U2>
1263 requires (sizeof...(_Elements) == 2)
1264 && (__constructible<const _U1&, const _U2&>())
1265 && (!__dangles<const _U1&, const _U2&>())
1266 constexpr explicit(!__convertible<const _U1&, const _U2&>())
1267 tuple(allocator_arg_t __tag, const _Alloc& __a,
1268 const pair<_U1, _U2>& __u)
1269 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1270 : _Inherited(__tag, __a, __u.first, __u.second)
1273 template<typename _Alloc, typename _U1, typename _U2>
1274 requires (sizeof...(_Elements) == 2)
1275 && (__constructible<const _U1&, const _U2&>())
1276 && (__dangles<const _U1&, const _U2&>())
1277 tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&) = delete;
1279 template<typename _Alloc, typename _U1, typename _U2>
1280 requires (sizeof...(_Elements) == 2)
1281 && (__constructible<_U1, _U2>())
1282 && (!__dangles<_U1, _U2>())
1283 constexpr explicit(!__convertible<_U1, _U2>())
1284 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __u)
1285 noexcept(__nothrow_constructible<_U1, _U2>())
1286 : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1289 template<typename _Alloc, typename _U1, typename _U2>
1290 requires (sizeof...(_Elements) == 2)
1291 && (__constructible<_U1, _U2>())
1292 && (__dangles<_U1, _U2>())
1293 tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&) = delete;
1295 #if __cpp_lib_ranges_zip // >= C++23
1296 template<typename _Alloc, typename _U1, typename _U2>
1297 requires (sizeof...(_Elements) == 2)
1298 && (__constructible<_U1&, _U2&>())
1299 && (!__dangles<_U1&, _U2&>())
1300 constexpr explicit(!__convertible<_U1&, _U2&>())
1301 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>& __u)
1302 noexcept(__nothrow_constructible<_U1&, _U2&>())
1303 : _Inherited(__tag, __a, __u.first, __u.second)
1306 template<typename _Alloc, typename _U1, typename _U2>
1307 requires (sizeof...(_Elements) == 2)
1308 && (__constructible<_U1&, _U2&>())
1309 && (__dangles<_U1&, _U2&>())
1310 tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&) = delete;
1312 template<typename _Alloc, typename _U1, typename _U2>
1313 requires (sizeof...(_Elements) == 2)
1314 && (__constructible<const _U1, const _U2>())
1315 && (!__dangles<const _U1, const _U2>())
1316 constexpr explicit(!__convertible<const _U1, const _U2>())
1317 tuple(allocator_arg_t __tag, const _Alloc& __a,
1318 const pair<_U1, _U2>&& __u)
1319 noexcept(__nothrow_constructible<const _U1, const _U2>())
1320 : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1323 template<typename _Alloc, typename _U1, typename _U2>
1324 requires (sizeof...(_Elements) == 2)
1325 && (__constructible<const _U1, const _U2>())
1326 && (__dangles<const _U1, const _U2>())
1327 tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&&) = delete;
1330 #if __cpp_lib_tuple_like // >= C++23
1331 template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
1332 requires (__constructible_from_tuple_like<_UTuple>())
1333 && (!__use_other_ctor<_UTuple>())
1334 && (!__dangles_from_tuple_like<_UTuple>())
1335 constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
1336 tuple(allocator_arg_t __tag, const _Alloc& __a, _UTuple&& __u)
1337 : _Inherited(__tuple_like_tag_t{},
1338 __tag, __a, std::forward<_UTuple>(__u),
1339 index_sequence_for<_Elements...>{})
1342 template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
1343 requires (__constructible_from_tuple_like<_UTuple>())
1344 && (!__use_other_ctor<_UTuple>())
1345 && (__dangles_from_tuple_like<_UTuple>())
1346 tuple(allocator_arg_t, const _Alloc&, _UTuple&&) = delete;
1349 #else // !(concepts && conditional_explicit)
1351 template<bool _Cond>
1352 using _TCC = _TupleConstraints<_Cond, _Elements...>;
1354 // Constraint for non-explicit default constructor
1355 template<bool _Dummy>
1356 using _ImplicitDefaultCtor = __enable_if_t<
1357 _TCC<_Dummy>::__is_implicitly_default_constructible(),
1360 // Constraint for explicit default constructor
1361 template<bool _Dummy>
1362 using _ExplicitDefaultCtor = __enable_if_t<
1363 _TCC<_Dummy>::__is_explicitly_default_constructible(),
1366 // Constraint for non-explicit constructors
1367 template<bool _Cond, typename... _Args>
1368 using _ImplicitCtor = __enable_if_t<
1369 _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
1372 // Constraint for non-explicit constructors
1373 template<bool _Cond, typename... _Args>
1374 using _ExplicitCtor = __enable_if_t<
1375 _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
1378 // Condition for noexcept-specifier of a constructor.
1379 template<typename... _UElements>
1380 static constexpr bool __nothrow_constructible()
1383 __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
1386 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1.
1387 template<typename _Up>
1388 static constexpr bool __valid_args()
1390 return sizeof...(_Elements) == 1
1391 && !is_same<tuple, __remove_cvref_t<_Up>>::value;
1394 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1.
1395 template<typename, typename, typename... _Tail>
1396 static constexpr bool __valid_args()
1397 { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); }
1399 /* Constraint for constructors with a tuple<UTypes...> parameter ensures
1400 * that the constructor is only viable when it would not interfere with
1401 * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&).
1402 * Such constructors are only viable if:
1403 * either sizeof...(Types) != 1,
1404 * or (when Types... expands to T and UTypes... expands to U)
1405 * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>,
1406 * and is_same_v<T, U> are all false.
1408 template<typename _Tuple, typename = tuple,
1409 typename = __remove_cvref_t<_Tuple>>
1410 struct _UseOtherCtor
1413 // If TUPLE is convertible to the single element in *this,
1414 // then TUPLE should match tuple(UTypes&&...) instead.
1415 template<typename _Tuple, typename _Tp, typename _Up>
1416 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>>
1417 : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>::type
1419 // If TUPLE and *this each have a single element of the same type,
1420 // then TUPLE should match a copy/move constructor instead.
1421 template<typename _Tuple, typename _Tp>
1422 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>>
1426 // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
1427 // and the single element in Types can be initialized from TUPLE,
1428 // or is the same type as tuple_element_t<0, TUPLE>.
1429 template<typename _Tuple>
1430 static constexpr bool __use_other_ctor()
1431 { return _UseOtherCtor<_Tuple>::value; }
1433 /// @cond undocumented
1434 #undef __glibcxx_no_dangling_refs
1435 #if __has_builtin(__reference_constructs_from_temporary) \
1436 && defined _GLIBCXX_DEBUG
1437 // Error if construction from U... would create a dangling ref.
1438 # if __cpp_fold_expressions
1439 # define __glibcxx_dangling_refs(U) \
1440 (__reference_constructs_from_temporary(_Elements, U) || ...)
1442 # define __glibcxx_dangling_refs(U) \
1443 __or_<__bool_constant<__reference_constructs_from_temporary(_Elements, U) \
1446 # define __glibcxx_no_dangling_refs(U) \
1447 static_assert(!__glibcxx_dangling_refs(U), \
1448 "std::tuple constructor creates a dangling reference")
1450 # define __glibcxx_no_dangling_refs(U)
1455 template<typename _Dummy = void,
1456 _ImplicitDefaultCtor<is_void<_Dummy>::value> = true>
1459 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1462 template<typename _Dummy = void,
1463 _ExplicitDefaultCtor<is_void<_Dummy>::value> = false>
1466 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1469 template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1470 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1472 tuple(const _Elements&... __elements)
1473 noexcept(__nothrow_constructible<const _Elements&...>())
1474 : _Inherited(__elements...) { }
1476 template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1477 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1479 tuple(const _Elements&... __elements)
1480 noexcept(__nothrow_constructible<const _Elements&...>())
1481 : _Inherited(__elements...) { }
1483 template<typename... _UElements,
1484 bool _Valid = __valid_args<_UElements...>(),
1485 _ImplicitCtor<_Valid, _UElements...> = true>
1487 tuple(_UElements&&... __elements)
1488 noexcept(__nothrow_constructible<_UElements...>())
1489 : _Inherited(std::forward<_UElements>(__elements)...)
1490 { __glibcxx_no_dangling_refs(_UElements&&); }
1492 template<typename... _UElements,
1493 bool _Valid = __valid_args<_UElements...>(),
1494 _ExplicitCtor<_Valid, _UElements...> = false>
1496 tuple(_UElements&&... __elements)
1497 noexcept(__nothrow_constructible<_UElements...>())
1498 : _Inherited(std::forward<_UElements>(__elements)...)
1499 { __glibcxx_no_dangling_refs(_UElements&&); }
1501 constexpr tuple(const tuple&) = default;
1503 constexpr tuple(tuple&&) = default;
1505 template<typename... _UElements,
1506 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1507 && !__use_other_ctor<const tuple<_UElements...>&>(),
1508 _ImplicitCtor<_Valid, const _UElements&...> = true>
1510 tuple(const tuple<_UElements...>& __in)
1511 noexcept(__nothrow_constructible<const _UElements&...>())
1512 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1513 { __glibcxx_no_dangling_refs(const _UElements&); }
1515 template<typename... _UElements,
1516 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1517 && !__use_other_ctor<const tuple<_UElements...>&>(),
1518 _ExplicitCtor<_Valid, const _UElements&...> = false>
1520 tuple(const tuple<_UElements...>& __in)
1521 noexcept(__nothrow_constructible<const _UElements&...>())
1522 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1523 { __glibcxx_no_dangling_refs(const _UElements&); }
1525 template<typename... _UElements,
1526 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1527 && !__use_other_ctor<tuple<_UElements...>&&>(),
1528 _ImplicitCtor<_Valid, _UElements...> = true>
1530 tuple(tuple<_UElements...>&& __in)
1531 noexcept(__nothrow_constructible<_UElements...>())
1532 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1533 { __glibcxx_no_dangling_refs(_UElements&&); }
1535 template<typename... _UElements,
1536 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1537 && !__use_other_ctor<tuple<_UElements...>&&>(),
1538 _ExplicitCtor<_Valid, _UElements...> = false>
1540 tuple(tuple<_UElements...>&& __in)
1541 noexcept(__nothrow_constructible<_UElements...>())
1542 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1543 { __glibcxx_no_dangling_refs(_UElements&&); }
1545 // Allocator-extended constructors.
1547 template<typename _Alloc,
1548 _ImplicitDefaultCtor<is_object<_Alloc>::value> = true>
1549 _GLIBCXX20_CONSTEXPR
1550 tuple(allocator_arg_t __tag, const _Alloc& __a)
1551 : _Inherited(__tag, __a) { }
1553 template<typename _Alloc,
1554 _ExplicitDefaultCtor<is_object<_Alloc>::value> = false>
1555 _GLIBCXX20_CONSTEXPR
1557 tuple(allocator_arg_t __tag, const _Alloc& __a)
1558 : _Inherited(__tag, __a) { }
1560 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1561 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1562 _GLIBCXX20_CONSTEXPR
1563 tuple(allocator_arg_t __tag, const _Alloc& __a,
1564 const _Elements&... __elements)
1565 : _Inherited(__tag, __a, __elements...) { }
1567 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1568 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1569 _GLIBCXX20_CONSTEXPR
1571 tuple(allocator_arg_t __tag, const _Alloc& __a,
1572 const _Elements&... __elements)
1573 : _Inherited(__tag, __a, __elements...) { }
1575 template<typename _Alloc, typename... _UElements,
1576 bool _Valid = __valid_args<_UElements...>(),
1577 _ImplicitCtor<_Valid, _UElements...> = true>
1578 _GLIBCXX20_CONSTEXPR
1579 tuple(allocator_arg_t __tag, const _Alloc& __a,
1580 _UElements&&... __elements)
1581 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1582 { __glibcxx_no_dangling_refs(_UElements&&); }
1584 template<typename _Alloc, typename... _UElements,
1585 bool _Valid = __valid_args<_UElements...>(),
1586 _ExplicitCtor<_Valid, _UElements...> = false>
1587 _GLIBCXX20_CONSTEXPR
1589 tuple(allocator_arg_t __tag, const _Alloc& __a,
1590 _UElements&&... __elements)
1591 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1592 { __glibcxx_no_dangling_refs(_UElements&&); }
1594 template<typename _Alloc>
1595 _GLIBCXX20_CONSTEXPR
1596 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1597 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1599 template<typename _Alloc>
1600 _GLIBCXX20_CONSTEXPR
1601 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1602 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1604 template<typename _Alloc, typename... _UElements,
1605 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1606 && !__use_other_ctor<const tuple<_UElements...>&>(),
1607 _ImplicitCtor<_Valid, const _UElements&...> = true>
1608 _GLIBCXX20_CONSTEXPR
1609 tuple(allocator_arg_t __tag, const _Alloc& __a,
1610 const tuple<_UElements...>& __in)
1611 : _Inherited(__tag, __a,
1612 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1613 { __glibcxx_no_dangling_refs(const _UElements&); }
1615 template<typename _Alloc, typename... _UElements,
1616 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1617 && !__use_other_ctor<const tuple<_UElements...>&>(),
1618 _ExplicitCtor<_Valid, const _UElements&...> = false>
1619 _GLIBCXX20_CONSTEXPR
1621 tuple(allocator_arg_t __tag, const _Alloc& __a,
1622 const tuple<_UElements...>& __in)
1623 : _Inherited(__tag, __a,
1624 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1625 { __glibcxx_no_dangling_refs(const _UElements&); }
1627 template<typename _Alloc, typename... _UElements,
1628 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1629 && !__use_other_ctor<tuple<_UElements...>&&>(),
1630 _ImplicitCtor<_Valid, _UElements...> = true>
1631 _GLIBCXX20_CONSTEXPR
1632 tuple(allocator_arg_t __tag, const _Alloc& __a,
1633 tuple<_UElements...>&& __in)
1634 : _Inherited(__tag, __a,
1635 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1636 { __glibcxx_no_dangling_refs(_UElements&&); }
1638 template<typename _Alloc, typename... _UElements,
1639 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1640 && !__use_other_ctor<tuple<_UElements...>&&>(),
1641 _ExplicitCtor<_Valid, _UElements...> = false>
1642 _GLIBCXX20_CONSTEXPR
1644 tuple(allocator_arg_t __tag, const _Alloc& __a,
1645 tuple<_UElements...>&& __in)
1646 : _Inherited(__tag, __a,
1647 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1648 { __glibcxx_no_dangling_refs(_UElements&&); }
1649 #endif // concepts && conditional_explicit
1653 #if __cpp_concepts && __cpp_consteval // >= C++20
1655 template<typename... _UTypes>
1656 static consteval bool
1659 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1660 return __and_v<is_assignable<_Elements&, _UTypes>...>;
1665 template<typename... _UTypes>
1666 static consteval bool
1667 __nothrow_assignable()
1669 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1670 return __and_v<is_nothrow_assignable<_Elements&, _UTypes>...>;
1675 #if __cpp_lib_ranges_zip // >= C++23
1676 template<typename... _UTypes>
1677 static consteval bool
1678 __const_assignable()
1680 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1681 return __and_v<is_assignable<const _Elements&, _UTypes>...>;
1687 #if __cpp_lib_tuple_like // >= C++23
1688 template<typename _UTuple>
1689 static consteval bool
1690 __assignable_from_tuple_like()
1692 return []<size_t... _Is>(index_sequence<_Is...>) {
1693 return __assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1694 }(index_sequence_for<_Elements...>{});
1697 template<typename _UTuple>
1698 static consteval bool
1699 __const_assignable_from_tuple_like()
1701 return []<size_t... _Is>(index_sequence<_Is...>) {
1702 return __const_assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1703 }(index_sequence_for<_Elements...>{});
1709 tuple& operator=(const tuple& __u) = delete;
1712 operator=(const tuple& __u)
1713 noexcept(__nothrow_assignable<const _Elements&...>())
1714 requires (__assignable<const _Elements&...>())
1716 this->_M_assign(__u);
1721 operator=(tuple&& __u)
1722 noexcept(__nothrow_assignable<_Elements...>())
1723 requires (__assignable<_Elements...>())
1725 this->_M_assign(std::move(__u));
1729 template<typename... _UTypes>
1730 requires (__assignable<const _UTypes&...>())
1732 operator=(const tuple<_UTypes...>& __u)
1733 noexcept(__nothrow_assignable<const _UTypes&...>())
1735 this->_M_assign(__u);
1739 template<typename... _UTypes>
1740 requires (__assignable<_UTypes...>())
1742 operator=(tuple<_UTypes...>&& __u)
1743 noexcept(__nothrow_assignable<_UTypes...>())
1745 this->_M_assign(std::move(__u));
1749 #if __cpp_lib_ranges_zip // >= C++23
1750 constexpr const tuple&
1751 operator=(const tuple& __u) const
1752 requires (__const_assignable<const _Elements&...>())
1754 this->_M_assign(__u);
1758 constexpr const tuple&
1759 operator=(tuple&& __u) const
1760 requires (__const_assignable<_Elements...>())
1762 this->_M_assign(std::move(__u));
1766 template<typename... _UTypes>
1767 constexpr const tuple&
1768 operator=(const tuple<_UTypes...>& __u) const
1769 requires (__const_assignable<const _UTypes&...>())
1771 this->_M_assign(__u);
1775 template<typename... _UTypes>
1776 constexpr const tuple&
1777 operator=(tuple<_UTypes...>&& __u) const
1778 requires (__const_assignable<_UTypes...>())
1780 this->_M_assign(std::move(__u));
1785 template<typename _U1, typename _U2>
1786 requires (__assignable<const _U1&, const _U2&>())
1788 operator=(const pair<_U1, _U2>& __u)
1789 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1791 this->_M_head(*this) = __u.first;
1792 this->_M_tail(*this)._M_head(*this) = __u.second;
1796 template<typename _U1, typename _U2>
1797 requires (__assignable<_U1, _U2>())
1799 operator=(pair<_U1, _U2>&& __u)
1800 noexcept(__nothrow_assignable<_U1, _U2>())
1802 this->_M_head(*this) = std::forward<_U1>(__u.first);
1803 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1807 #if __cpp_lib_ranges_zip // >= C++23
1808 template<typename _U1, typename _U2>
1809 requires (__const_assignable<const _U1&, const _U2>())
1810 constexpr const tuple&
1811 operator=(const pair<_U1, _U2>& __u) const
1813 this->_M_head(*this) = __u.first;
1814 this->_M_tail(*this)._M_head(*this) = __u.second;
1818 template<typename _U1, typename _U2>
1819 requires (__const_assignable<_U1, _U2>())
1820 constexpr const tuple&
1821 operator=(pair<_U1, _U2>&& __u) const
1823 this->_M_head(*this) = std::forward<_U1>(__u.first);
1824 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1829 #if __cpp_lib_tuple_like // >= C++23
1830 template<__eligible_tuple_like<tuple> _UTuple>
1831 requires (__assignable_from_tuple_like<_UTuple>())
1833 operator=(_UTuple&& __u)
1835 this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1839 template<__eligible_tuple_like<tuple> _UTuple>
1840 requires (__const_assignable_from_tuple_like<_UTuple>())
1841 constexpr const tuple&
1842 operator=(_UTuple&& __u) const
1844 this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1848 template<__tuple_like _UTuple>
1849 requires (!__is_tuple_v<_UTuple>)
1850 friend constexpr bool
1851 operator==(const tuple& __t, const _UTuple& __u)
1853 static_assert(sizeof...(_Elements) == tuple_size_v<_UTuple>,
1854 "tuple objects can only be compared if they have equal sizes.");
1855 return [&]<size_t... _Is>(index_sequence<_Is...>) {
1856 return (bool(std::get<_Is>(__t) == std::get<_Is>(__u))
1858 }(index_sequence_for<_Elements...>{});
1861 template<__tuple_like _UTuple,
1862 typename = make_index_sequence<tuple_size_v<_UTuple>>>
1863 struct __tuple_like_common_comparison_category;
1865 template<__tuple_like _UTuple, size_t... _Is>
1867 { typename void_t<__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>; }
1868 struct __tuple_like_common_comparison_category<_UTuple, index_sequence<_Is...>>
1870 using type = common_comparison_category_t
1871 <__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>;
1874 template<__tuple_like _UTuple>
1875 requires (!__is_tuple_v<_UTuple>)
1876 friend constexpr typename __tuple_like_common_comparison_category<_UTuple>::type
1877 operator<=>(const tuple& __t, const _UTuple& __u)
1879 using _Cat = typename __tuple_like_common_comparison_category<_UTuple>::type;
1880 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Elements...>());
1884 #else // ! (concepts && consteval)
1887 template<typename... _UElements>
1889 __enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
1891 { return __and_<is_assignable<_Elements&, _UElements>...>::value; }
1893 // Condition for noexcept-specifier of an assignment operator.
1894 template<typename... _UElements>
1895 static constexpr bool __nothrow_assignable()
1898 __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
1903 _GLIBCXX20_CONSTEXPR
1905 operator=(__conditional_t<__assignable<const _Elements&...>(),
1907 const __nonesuch&> __in)
1908 noexcept(__nothrow_assignable<const _Elements&...>())
1910 this->_M_assign(__in);
1914 _GLIBCXX20_CONSTEXPR
1916 operator=(__conditional_t<__assignable<_Elements...>(),
1919 noexcept(__nothrow_assignable<_Elements...>())
1921 this->_M_assign(std::move(__in));
1925 template<typename... _UElements>
1926 _GLIBCXX20_CONSTEXPR
1927 __enable_if_t<__assignable<const _UElements&...>(), tuple&>
1928 operator=(const tuple<_UElements...>& __in)
1929 noexcept(__nothrow_assignable<const _UElements&...>())
1931 this->_M_assign(__in);
1935 template<typename... _UElements>
1936 _GLIBCXX20_CONSTEXPR
1937 __enable_if_t<__assignable<_UElements...>(), tuple&>
1938 operator=(tuple<_UElements...>&& __in)
1939 noexcept(__nothrow_assignable<_UElements...>())
1941 this->_M_assign(std::move(__in));
1944 #endif // concepts && consteval
1947 _GLIBCXX20_CONSTEXPR
1950 noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
1951 { _Inherited::_M_swap(__in); }
1953 #if __cpp_lib_ranges_zip // >= C++23
1954 // As an extension, we constrain the const swap member function in order
1955 // to continue accepting explicit instantiation of tuples whose elements
1956 // are not all const swappable. Without this constraint, such an
1957 // explicit instantiation would also instantiate the ill-formed body of
1958 // this function and yield a hard error. This constraint shouldn't
1959 // affect the behavior of valid programs.
1961 swap(const tuple& __in) const
1962 noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
1963 requires (is_swappable_v<const _Elements> && ...)
1964 { _Inherited::_M_swap(__in); }
1968 #if __cpp_deduction_guides >= 201606
1969 template<typename... _UTypes>
1970 tuple(_UTypes...) -> tuple<_UTypes...>;
1971 template<typename _T1, typename _T2>
1972 tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
1973 template<typename _Alloc, typename... _UTypes>
1974 tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
1975 template<typename _Alloc, typename _T1, typename _T2>
1976 tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
1977 template<typename _Alloc, typename... _UTypes>
1978 tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
1981 // Explicit specialization, zero-element tuple.
1986 _GLIBCXX20_CONSTEXPR
1987 void swap(tuple&) noexcept { /* no-op */ }
1988 #if __cpp_lib_ranges_zip // >= C++23
1989 constexpr void swap(const tuple&) const noexcept { /* no-op */ }
1991 // We need the default since we're going to define no-op
1992 // allocator constructors.
1994 // No-op allocator constructors.
1995 template<typename _Alloc>
1996 _GLIBCXX20_CONSTEXPR
1997 tuple(allocator_arg_t, const _Alloc&) noexcept { }
1998 template<typename _Alloc>
1999 _GLIBCXX20_CONSTEXPR
2000 tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
2003 #if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20
2004 /// Partial specialization, 2-element tuple.
2005 /// Includes construction and assignment from a pair.
2006 template<typename _T1, typename _T2>
2007 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
2009 typedef _Tuple_impl<0, _T1, _T2> _Inherited;
2011 // Constraint for non-explicit default constructor
2012 template<bool _Dummy, typename _U1, typename _U2>
2013 using _ImplicitDefaultCtor = __enable_if_t<
2014 _TupleConstraints<_Dummy, _U1, _U2>::
2015 __is_implicitly_default_constructible(),
2018 // Constraint for explicit default constructor
2019 template<bool _Dummy, typename _U1, typename _U2>
2020 using _ExplicitDefaultCtor = __enable_if_t<
2021 _TupleConstraints<_Dummy, _U1, _U2>::
2022 __is_explicitly_default_constructible(),
2025 template<bool _Dummy>
2026 using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
2028 // Constraint for non-explicit constructors
2029 template<bool _Cond, typename _U1, typename _U2>
2030 using _ImplicitCtor = __enable_if_t<
2031 _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
2034 // Constraint for non-explicit constructors
2035 template<bool _Cond, typename _U1, typename _U2>
2036 using _ExplicitCtor = __enable_if_t<
2037 _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
2040 template<typename _U1, typename _U2>
2041 static constexpr bool __assignable()
2043 return __and_<is_assignable<_T1&, _U1>,
2044 is_assignable<_T2&, _U2>>::value;
2047 template<typename _U1, typename _U2>
2048 static constexpr bool __nothrow_assignable()
2050 return __and_<is_nothrow_assignable<_T1&, _U1>,
2051 is_nothrow_assignable<_T2&, _U2>>::value;
2054 template<typename _U1, typename _U2>
2055 static constexpr bool __nothrow_constructible()
2057 return __and_<is_nothrow_constructible<_T1, _U1>,
2058 is_nothrow_constructible<_T2, _U2>>::value;
2061 static constexpr bool __nothrow_default_constructible()
2063 return __and_<is_nothrow_default_constructible<_T1>,
2064 is_nothrow_default_constructible<_T2>>::value;
2067 template<typename _U1>
2068 static constexpr bool __is_alloc_arg()
2069 { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
2071 /// @cond undocumented
2072 #undef __glibcxx_no_dangling_refs
2073 // Error if construction from _U1 and _U2 would create a dangling ref.
2074 #if __has_builtin(__reference_constructs_from_temporary) \
2075 && defined _GLIBCXX_DEBUG
2076 # define __glibcxx_no_dangling_refs(_U1, _U2) \
2077 static_assert(!__reference_constructs_from_temporary(_T1, _U1) \
2078 && !__reference_constructs_from_temporary(_T2, _U2), \
2079 "std::tuple constructor creates a dangling reference")
2081 # define __glibcxx_no_dangling_refs(_U1, _U2)
2086 template<bool _Dummy = true,
2087 _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
2090 noexcept(__nothrow_default_constructible())
2093 template<bool _Dummy = true,
2094 _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
2097 noexcept(__nothrow_default_constructible())
2100 template<bool _Dummy = true,
2101 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2103 tuple(const _T1& __a1, const _T2& __a2)
2104 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2105 : _Inherited(__a1, __a2) { }
2107 template<bool _Dummy = true,
2108 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2110 tuple(const _T1& __a1, const _T2& __a2)
2111 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2112 : _Inherited(__a1, __a2) { }
2114 template<typename _U1, typename _U2,
2115 _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
2117 tuple(_U1&& __a1, _U2&& __a2)
2118 noexcept(__nothrow_constructible<_U1, _U2>())
2119 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2120 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2122 template<typename _U1, typename _U2,
2123 _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
2125 tuple(_U1&& __a1, _U2&& __a2)
2126 noexcept(__nothrow_constructible<_U1, _U2>())
2127 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2128 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2130 constexpr tuple(const tuple&) = default;
2132 constexpr tuple(tuple&&) = default;
2134 template<typename _U1, typename _U2,
2135 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2137 tuple(const tuple<_U1, _U2>& __in)
2138 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2139 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2140 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2142 template<typename _U1, typename _U2,
2143 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2145 tuple(const tuple<_U1, _U2>& __in)
2146 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2147 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2148 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2150 template<typename _U1, typename _U2,
2151 _ImplicitCtor<true, _U1, _U2> = true>
2153 tuple(tuple<_U1, _U2>&& __in)
2154 noexcept(__nothrow_constructible<_U1, _U2>())
2155 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2156 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2158 template<typename _U1, typename _U2,
2159 _ExplicitCtor<true, _U1, _U2> = false>
2161 tuple(tuple<_U1, _U2>&& __in)
2162 noexcept(__nothrow_constructible<_U1, _U2>())
2163 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2164 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2166 template<typename _U1, typename _U2,
2167 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2169 tuple(const pair<_U1, _U2>& __in)
2170 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2171 : _Inherited(__in.first, __in.second)
2172 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2174 template<typename _U1, typename _U2,
2175 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2177 tuple(const pair<_U1, _U2>& __in)
2178 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2179 : _Inherited(__in.first, __in.second)
2180 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2182 template<typename _U1, typename _U2,
2183 _ImplicitCtor<true, _U1, _U2> = true>
2185 tuple(pair<_U1, _U2>&& __in)
2186 noexcept(__nothrow_constructible<_U1, _U2>())
2187 : _Inherited(std::forward<_U1>(__in.first),
2188 std::forward<_U2>(__in.second))
2189 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2191 template<typename _U1, typename _U2,
2192 _ExplicitCtor<true, _U1, _U2> = false>
2194 tuple(pair<_U1, _U2>&& __in)
2195 noexcept(__nothrow_constructible<_U1, _U2>())
2196 : _Inherited(std::forward<_U1>(__in.first),
2197 std::forward<_U2>(__in.second))
2198 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2200 // Allocator-extended constructors.
2202 template<typename _Alloc,
2203 _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
2204 _GLIBCXX20_CONSTEXPR
2205 tuple(allocator_arg_t __tag, const _Alloc& __a)
2206 : _Inherited(__tag, __a) { }
2208 template<typename _Alloc,
2209 _ExplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = false>
2210 _GLIBCXX20_CONSTEXPR
2212 tuple(allocator_arg_t __tag, const _Alloc& __a)
2213 : _Inherited(__tag, __a) { }
2215 template<typename _Alloc, bool _Dummy = true,
2216 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2217 _GLIBCXX20_CONSTEXPR
2218 tuple(allocator_arg_t __tag, const _Alloc& __a,
2219 const _T1& __a1, const _T2& __a2)
2220 : _Inherited(__tag, __a, __a1, __a2) { }
2222 template<typename _Alloc, bool _Dummy = true,
2223 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2225 _GLIBCXX20_CONSTEXPR
2226 tuple(allocator_arg_t __tag, const _Alloc& __a,
2227 const _T1& __a1, const _T2& __a2)
2228 : _Inherited(__tag, __a, __a1, __a2) { }
2230 template<typename _Alloc, typename _U1, typename _U2,
2231 _ImplicitCtor<true, _U1, _U2> = true>
2232 _GLIBCXX20_CONSTEXPR
2233 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
2234 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2235 std::forward<_U2>(__a2))
2236 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2238 template<typename _Alloc, typename _U1, typename _U2,
2239 _ExplicitCtor<true, _U1, _U2> = false>
2241 _GLIBCXX20_CONSTEXPR
2242 tuple(allocator_arg_t __tag, const _Alloc& __a,
2243 _U1&& __a1, _U2&& __a2)
2244 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2245 std::forward<_U2>(__a2))
2246 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2248 template<typename _Alloc>
2249 _GLIBCXX20_CONSTEXPR
2250 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
2251 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
2253 template<typename _Alloc>
2254 _GLIBCXX20_CONSTEXPR
2255 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
2256 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
2258 template<typename _Alloc, typename _U1, typename _U2,
2259 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2260 _GLIBCXX20_CONSTEXPR
2261 tuple(allocator_arg_t __tag, const _Alloc& __a,
2262 const tuple<_U1, _U2>& __in)
2263 : _Inherited(__tag, __a,
2264 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2265 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2267 template<typename _Alloc, typename _U1, typename _U2,
2268 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2270 _GLIBCXX20_CONSTEXPR
2271 tuple(allocator_arg_t __tag, const _Alloc& __a,
2272 const tuple<_U1, _U2>& __in)
2273 : _Inherited(__tag, __a,
2274 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2275 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2277 template<typename _Alloc, typename _U1, typename _U2,
2278 _ImplicitCtor<true, _U1, _U2> = true>
2279 _GLIBCXX20_CONSTEXPR
2280 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2281 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2282 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2284 template<typename _Alloc, typename _U1, typename _U2,
2285 _ExplicitCtor<true, _U1, _U2> = false>
2287 _GLIBCXX20_CONSTEXPR
2288 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2289 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2290 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2292 template<typename _Alloc, typename _U1, typename _U2,
2293 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2294 _GLIBCXX20_CONSTEXPR
2295 tuple(allocator_arg_t __tag, const _Alloc& __a,
2296 const pair<_U1, _U2>& __in)
2297 : _Inherited(__tag, __a, __in.first, __in.second)
2298 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2300 template<typename _Alloc, typename _U1, typename _U2,
2301 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2303 _GLIBCXX20_CONSTEXPR
2304 tuple(allocator_arg_t __tag, const _Alloc& __a,
2305 const pair<_U1, _U2>& __in)
2306 : _Inherited(__tag, __a, __in.first, __in.second)
2307 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2309 template<typename _Alloc, typename _U1, typename _U2,
2310 _ImplicitCtor<true, _U1, _U2> = true>
2311 _GLIBCXX20_CONSTEXPR
2312 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2313 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2314 std::forward<_U2>(__in.second))
2315 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2317 template<typename _Alloc, typename _U1, typename _U2,
2318 _ExplicitCtor<true, _U1, _U2> = false>
2320 _GLIBCXX20_CONSTEXPR
2321 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2322 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2323 std::forward<_U2>(__in.second))
2324 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2326 // Tuple assignment.
2328 _GLIBCXX20_CONSTEXPR
2330 operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
2332 const __nonesuch&> __in)
2333 noexcept(__nothrow_assignable<const _T1&, const _T2&>())
2335 this->_M_assign(__in);
2339 _GLIBCXX20_CONSTEXPR
2341 operator=(__conditional_t<__assignable<_T1, _T2>(),
2344 noexcept(__nothrow_assignable<_T1, _T2>())
2346 this->_M_assign(std::move(__in));
2350 template<typename _U1, typename _U2>
2351 _GLIBCXX20_CONSTEXPR
2352 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2353 operator=(const tuple<_U1, _U2>& __in)
2354 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2356 this->_M_assign(__in);
2360 template<typename _U1, typename _U2>
2361 _GLIBCXX20_CONSTEXPR
2362 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2363 operator=(tuple<_U1, _U2>&& __in)
2364 noexcept(__nothrow_assignable<_U1, _U2>())
2366 this->_M_assign(std::move(__in));
2370 template<typename _U1, typename _U2>
2371 _GLIBCXX20_CONSTEXPR
2372 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2373 operator=(const pair<_U1, _U2>& __in)
2374 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2376 this->_M_head(*this) = __in.first;
2377 this->_M_tail(*this)._M_head(*this) = __in.second;
2381 template<typename _U1, typename _U2>
2382 _GLIBCXX20_CONSTEXPR
2383 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2384 operator=(pair<_U1, _U2>&& __in)
2385 noexcept(__nothrow_assignable<_U1, _U2>())
2387 this->_M_head(*this) = std::forward<_U1>(__in.first);
2388 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
2392 _GLIBCXX20_CONSTEXPR
2395 noexcept(__and_<__is_nothrow_swappable<_T1>,
2396 __is_nothrow_swappable<_T2>>::value)
2397 { _Inherited::_M_swap(__in); }
2399 #endif // concepts && conditional_explicit
2401 /// class tuple_size
2402 template<typename... _Elements>
2403 struct tuple_size<tuple<_Elements...>>
2404 : public integral_constant<size_t, sizeof...(_Elements)> { };
2406 #if __cplusplus >= 201703L
2407 template<typename... _Types>
2408 inline constexpr size_t tuple_size_v<tuple<_Types...>>
2409 = sizeof...(_Types);
2411 template<typename... _Types>
2412 inline constexpr size_t tuple_size_v<const tuple<_Types...>>
2413 = sizeof...(_Types);
2416 /// Trait to get the Ith element type from a tuple.
2417 template<size_t __i, typename... _Types>
2418 struct tuple_element<__i, tuple<_Types...>>
2420 static_assert(__i < sizeof...(_Types), "tuple index must be in range");
2422 using type = typename _Nth_type<__i, _Types...>::type;
2425 template<size_t __i, typename _Head, typename... _Tail>
2427 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2428 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2430 template<size_t __i, typename _Head, typename... _Tail>
2431 constexpr const _Head&
2432 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2433 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2435 // Deleted overload to improve diagnostics for invalid indices
2436 template<size_t __i, typename... _Types>
2437 __enable_if_t<(__i >= sizeof...(_Types))>
2438 __get_helper(const tuple<_Types...>&) = delete;
2440 /// Return a reference to the ith element of a tuple.
2441 template<size_t __i, typename... _Elements>
2442 constexpr __tuple_element_t<__i, tuple<_Elements...>>&
2443 get(tuple<_Elements...>& __t) noexcept
2444 { return std::__get_helper<__i>(__t); }
2446 /// Return a const reference to the ith element of a const tuple.
2447 template<size_t __i, typename... _Elements>
2448 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
2449 get(const tuple<_Elements...>& __t) noexcept
2450 { return std::__get_helper<__i>(__t); }
2452 /// Return an rvalue reference to the ith element of a tuple rvalue.
2453 template<size_t __i, typename... _Elements>
2454 constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
2455 get(tuple<_Elements...>&& __t) noexcept
2457 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2458 return std::forward<__element_type>(std::__get_helper<__i>(__t));
2461 /// Return a const rvalue reference to the ith element of a const tuple rvalue.
2462 template<size_t __i, typename... _Elements>
2463 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
2464 get(const tuple<_Elements...>&& __t) noexcept
2466 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2467 return std::forward<const __element_type>(std::__get_helper<__i>(__t));
2470 /// @cond undocumented
2471 // Deleted overload chosen for invalid indices.
2472 template<size_t __i, typename... _Elements>
2473 constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
2474 get(const tuple<_Elements...>&) = delete;
2477 #ifdef __cpp_lib_tuples_by_type // C++ >= 14
2478 /// Return a reference to the unique element of type _Tp of a tuple.
2479 template <typename _Tp, typename... _Types>
2481 get(tuple<_Types...>& __t) noexcept
2483 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2484 static_assert(__idx < sizeof...(_Types),
2485 "the type T in std::get<T> must occur exactly once in the tuple");
2486 return std::__get_helper<__idx>(__t);
2489 /// Return a reference to the unique element of type _Tp of a tuple rvalue.
2490 template <typename _Tp, typename... _Types>
2492 get(tuple<_Types...>&& __t) noexcept
2494 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2495 static_assert(__idx < sizeof...(_Types),
2496 "the type T in std::get<T> must occur exactly once in the tuple");
2497 return std::forward<_Tp>(std::__get_helper<__idx>(__t));
2500 /// Return a const reference to the unique element of type _Tp of a tuple.
2501 template <typename _Tp, typename... _Types>
2502 constexpr const _Tp&
2503 get(const tuple<_Types...>& __t) noexcept
2505 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2506 static_assert(__idx < sizeof...(_Types),
2507 "the type T in std::get<T> must occur exactly once in the tuple");
2508 return std::__get_helper<__idx>(__t);
2511 /// Return a const reference to the unique element of type _Tp of
2512 /// a const tuple rvalue.
2513 template <typename _Tp, typename... _Types>
2514 constexpr const _Tp&&
2515 get(const tuple<_Types...>&& __t) noexcept
2517 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2518 static_assert(__idx < sizeof...(_Types),
2519 "the type T in std::get<T> must occur exactly once in the tuple");
2520 return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
2524 // This class performs the comparison operations on tuples
2525 template<typename _Tp, typename _Up, size_t __i, size_t __size>
2526 struct __tuple_compare
2528 static constexpr bool
2529 __eq(const _Tp& __t, const _Up& __u)
2531 return bool(std::get<__i>(__t) == std::get<__i>(__u))
2532 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
2535 static constexpr bool
2536 __less(const _Tp& __t, const _Up& __u)
2538 return bool(std::get<__i>(__t) < std::get<__i>(__u))
2539 || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
2540 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
2544 template<typename _Tp, typename _Up, size_t __size>
2545 struct __tuple_compare<_Tp, _Up, __size, __size>
2547 static constexpr bool
2548 __eq(const _Tp&, const _Up&) { return true; }
2550 static constexpr bool
2551 __less(const _Tp&, const _Up&) { return false; }
2554 template<typename... _TElements, typename... _UElements>
2556 operator==(const tuple<_TElements...>& __t,
2557 const tuple<_UElements...>& __u)
2559 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2560 "tuple objects can only be compared if they have equal sizes.");
2561 using __compare = __tuple_compare<tuple<_TElements...>,
2562 tuple<_UElements...>,
2563 0, sizeof...(_TElements)>;
2564 return __compare::__eq(__t, __u);
2567 #if __cpp_lib_three_way_comparison
2568 template<typename _Cat, typename _Tp, typename _Up>
2570 __tuple_cmp(const _Tp&, const _Up&, index_sequence<>)
2571 { return _Cat::equivalent; }
2573 template<typename _Cat, typename _Tp, typename _Up,
2574 size_t _Idx0, size_t... _Idxs>
2576 __tuple_cmp(const _Tp& __t, const _Up& __u,
2577 index_sequence<_Idx0, _Idxs...>)
2580 = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u));
2583 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>());
2586 template<typename... _Tps, typename... _Ups>
2588 common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
2589 operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
2592 = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
2593 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
2596 template<typename... _TElements, typename... _UElements>
2598 operator<(const tuple<_TElements...>& __t,
2599 const tuple<_UElements...>& __u)
2601 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2602 "tuple objects can only be compared if they have equal sizes.");
2603 using __compare = __tuple_compare<tuple<_TElements...>,
2604 tuple<_UElements...>,
2605 0, sizeof...(_TElements)>;
2606 return __compare::__less(__t, __u);
2609 template<typename... _TElements, typename... _UElements>
2611 operator!=(const tuple<_TElements...>& __t,
2612 const tuple<_UElements...>& __u)
2613 { return !(__t == __u); }
2615 template<typename... _TElements, typename... _UElements>
2617 operator>(const tuple<_TElements...>& __t,
2618 const tuple<_UElements...>& __u)
2619 { return __u < __t; }
2621 template<typename... _TElements, typename... _UElements>
2623 operator<=(const tuple<_TElements...>& __t,
2624 const tuple<_UElements...>& __u)
2625 { return !(__u < __t); }
2627 template<typename... _TElements, typename... _UElements>
2629 operator>=(const tuple<_TElements...>& __t,
2630 const tuple<_UElements...>& __u)
2631 { return !(__t < __u); }
2632 #endif // three_way_comparison
2635 /// Create a tuple containing copies of the arguments
2636 template<typename... _Elements>
2637 constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
2638 make_tuple(_Elements&&... __args)
2640 typedef tuple<typename __decay_and_strip<_Elements>::__type...>
2642 return __result_type(std::forward<_Elements>(__args)...);
2645 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2646 // 2275. Why is forward_as_tuple not constexpr?
2647 /// Create a tuple of lvalue or rvalue references to the arguments
2648 template<typename... _Elements>
2649 constexpr tuple<_Elements&&...>
2650 forward_as_tuple(_Elements&&... __args) noexcept
2651 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2653 /// @cond undocumented
2654 template<size_t, typename, typename, size_t>
2655 struct __make_tuple_impl;
2657 template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
2658 struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
2659 : __make_tuple_impl<_Idx + 1,
2660 tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
2664 template<size_t _Nm, typename _Tuple, typename... _Tp>
2665 struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
2667 typedef tuple<_Tp...> __type;
2670 template<typename _Tuple>
2671 struct __do_make_tuple
2672 : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
2675 // Returns the std::tuple equivalent of a tuple-like type.
2676 template<typename _Tuple>
2678 : public __do_make_tuple<__remove_cvref_t<_Tuple>>
2681 // Combines several std::tuple's into a single one.
2682 template<typename...>
2683 struct __combine_tuples;
2686 struct __combine_tuples<>
2688 typedef tuple<> __type;
2691 template<typename... _Ts>
2692 struct __combine_tuples<tuple<_Ts...>>
2694 typedef tuple<_Ts...> __type;
2697 template<typename... _T1s, typename... _T2s, typename... _Rem>
2698 struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
2700 typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
2701 _Rem...>::__type __type;
2704 // Computes the result type of tuple_cat given a set of tuple-like types.
2705 template<typename... _Tpls>
2706 struct __tuple_cat_result
2708 typedef typename __combine_tuples
2709 <typename __make_tuple<_Tpls>::__type...>::__type __type;
2712 // Helper to determine the index set for the first tuple-like
2713 // type of a given set.
2714 template<typename...>
2715 struct __make_1st_indices;
2718 struct __make_1st_indices<>
2720 typedef _Index_tuple<> __type;
2723 template<typename _Tp, typename... _Tpls>
2724 struct __make_1st_indices<_Tp, _Tpls...>
2726 typedef typename _Build_index_tuple<tuple_size<
2727 typename remove_reference<_Tp>::type>::value>::__type __type;
2730 // Performs the actual concatenation by step-wise expanding tuple-like
2731 // objects into the elements, which are finally forwarded into the
2733 template<typename _Ret, typename _Indices, typename... _Tpls>
2734 struct __tuple_concater;
2736 template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2737 struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2739 template<typename... _Us>
2740 static constexpr _Ret
2741 _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2743 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2744 typedef __tuple_concater<_Ret, __idx, _Tpls...> __next;
2745 return __next::_S_do(std::forward<_Tpls>(__tps)...,
2746 std::forward<_Us>(__us)...,
2747 std::get<_Is>(std::forward<_Tp>(__tp))...);
2751 template<typename _Ret>
2752 struct __tuple_concater<_Ret, _Index_tuple<>>
2754 template<typename... _Us>
2755 static constexpr _Ret
2756 _S_do(_Us&&... __us)
2758 return _Ret(std::forward<_Us>(__us)...);
2762 template<typename... _Tps>
2763 struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2767 /// Create a `tuple` containing all elements from multiple tuple-like objects
2768 #if __cpp_lib_tuple_like // >= C++23
2769 template<__tuple_like... _Tpls>
2771 template<typename... _Tpls, typename = typename
2772 enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2775 tuple_cat(_Tpls&&... __tpls)
2776 -> typename __tuple_cat_result<_Tpls...>::__type
2778 typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2779 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2780 typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2781 return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2784 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2785 // 2301. Why is tie not constexpr?
2786 /// Return a tuple of lvalue references bound to the arguments
2787 template<typename... _Elements>
2788 constexpr tuple<_Elements&...>
2789 tie(_Elements&... __args) noexcept
2790 { return tuple<_Elements&...>(__args...); }
2792 /// Exchange the values of two tuples
2793 template<typename... _Elements>
2794 _GLIBCXX20_CONSTEXPR
2796 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2797 // Constrained free swap overload, see p0185r1
2798 typename enable_if<__and_<__is_swappable<_Elements>...>::value
2803 swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
2804 noexcept(noexcept(__x.swap(__y)))
2807 #if __cpp_lib_ranges_zip // >= C++23
2808 template<typename... _Elements>
2809 requires (is_swappable_v<const _Elements> && ...)
2811 swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2812 noexcept(noexcept(__x.swap(__y)))
2816 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2817 /// Exchange the values of two const tuples (if const elements can be swapped)
2818 template<typename... _Elements>
2819 _GLIBCXX20_CONSTEXPR
2820 typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2821 swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2824 // A class (and instance) which can be used in 'tie' when an element
2825 // of a tuple is not required.
2826 // _GLIBCXX14_CONSTEXPR
2827 // 2933. PR for LWG 2773 could be clearer
2828 struct _Swallow_assign
2831 _GLIBCXX14_CONSTEXPR const _Swallow_assign&
2832 operator=(const _Tp&) const
2836 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2837 // 2773. Making std::ignore constexpr
2838 /** Used with `std::tie` to ignore an element of a tuple
2840 * When using `std::tie` to assign the elements of a tuple to variables,
2841 * unwanted elements can be ignored by using `std::ignore`. For example:
2845 * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3);
2848 * This assignment will perform `x=1; std::ignore=2; y=3;` which results
2849 * in the second element being ignored.
2853 _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{};
2855 /// Partial specialization for tuples
2856 template<typename... _Types, typename _Alloc>
2857 struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2859 // See stl_pair.h...
2860 /** "piecewise construction" using a tuple of arguments for each member.
2862 * @param __first Arguments for the first member of the pair.
2863 * @param __second Arguments for the second member of the pair.
2865 * The elements of each tuple will be used as the constructor arguments
2866 * for the data members of the pair.
2868 template<class _T1, class _T2>
2869 template<typename... _Args1, typename... _Args2>
2870 _GLIBCXX20_CONSTEXPR
2873 pair(piecewise_construct_t,
2874 tuple<_Args1...> __first, tuple<_Args2...> __second)
2875 : pair(__first, __second,
2876 typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2877 typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2880 template<class _T1, class _T2>
2881 template<typename... _Args1, size_t... _Indexes1,
2882 typename... _Args2, size_t... _Indexes2>
2883 _GLIBCXX20_CONSTEXPR inline
2885 pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2886 _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2887 : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2888 second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2891 #if defined(__cpp_lib_apply) || defined(__cpp_lib_make_from_tuple) // C++ >= 17
2892 // Unpack a std::tuple into a type trait and use its value.
2893 // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2894 // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2895 // Otherwise the result is false (because we don't know if std::get throws).
2896 template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2897 inline constexpr bool __unpack_std_tuple = false;
2899 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2900 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2901 = _Trait<_Tp, _Up...>::value;
2903 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2904 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2905 = _Trait<_Tp, _Up&...>::value;
2907 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2908 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2909 = _Trait<_Tp, const _Up...>::value;
2911 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2912 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2913 = _Trait<_Tp, const _Up&...>::value;
2916 #ifdef __cpp_lib_apply // C++ >= 17
2917 template <typename _Fn, typename _Tuple, size_t... _Idx>
2918 constexpr decltype(auto)
2919 __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2921 return std::__invoke(std::forward<_Fn>(__f),
2922 std::get<_Idx>(std::forward<_Tuple>(__t))...);
2925 #if __cpp_lib_tuple_like // >= C++23
2926 template <typename _Fn, __tuple_like _Tuple>
2928 template <typename _Fn, typename _Tuple>
2930 constexpr decltype(auto)
2931 apply(_Fn&& __f, _Tuple&& __t)
2932 noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2935 = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2936 return std::__apply_impl(std::forward<_Fn>(__f),
2937 std::forward<_Tuple>(__t),
2942 #ifdef __cpp_lib_make_from_tuple // C++ >= 17
2943 template <typename _Tp, typename _Tuple, size_t... _Idx>
2945 __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
2946 { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
2948 #if __cpp_lib_tuple_like // >= C++23
2949 template <typename _Tp, __tuple_like _Tuple>
2951 template <typename _Tp, typename _Tuple>
2954 make_from_tuple(_Tuple&& __t)
2955 noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
2957 constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
2958 #if __has_builtin(__reference_constructs_from_temporary)
2959 if constexpr (__n == 1)
2961 using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
2962 static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
2965 return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
2966 make_index_sequence<__n>{});
2970 #if __cpp_lib_tuple_like // >= C++23
2971 template<__tuple_like _TTuple, __tuple_like _UTuple,
2972 template<typename> class _TQual, template<typename> class _UQual,
2973 typename = make_index_sequence<tuple_size_v<_TTuple>>>
2974 struct __tuple_like_common_reference;
2976 template<__tuple_like _TTuple, __tuple_like _UTuple,
2977 template<typename> class _TQual, template<typename> class _UQual,
2980 { typename tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2981 _UQual<tuple_element_t<_Is, _UTuple>>>...>; }
2982 struct __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual, index_sequence<_Is...>>
2984 using type = tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2985 _UQual<tuple_element_t<_Is, _UTuple>>>...>;
2988 template<__tuple_like _TTuple, __tuple_like _UTuple,
2989 template<typename> class _TQual, template<typename> class _UQual>
2990 requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
2991 && is_same_v<_TTuple, decay_t<_TTuple>>
2992 && is_same_v<_UTuple, decay_t<_UTuple>>
2993 && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
2994 && requires { typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type; }
2995 struct basic_common_reference<_TTuple, _UTuple, _TQual, _UQual>
2997 using type = typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type;
3000 template<__tuple_like _TTuple, __tuple_like _UTuple,
3001 typename = make_index_sequence<tuple_size_v<_TTuple>>>
3002 struct __tuple_like_common_type;
3004 template<__tuple_like _TTuple, __tuple_like _UTuple, size_t... _Is>
3006 { typename tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3007 tuple_element_t<_Is, _UTuple>>...>; }
3008 struct __tuple_like_common_type<_TTuple, _UTuple, index_sequence<_Is...>>
3010 using type = tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3011 tuple_element_t<_Is, _UTuple>>...>;
3014 template<__tuple_like _TTuple, __tuple_like _UTuple>
3015 requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
3016 && is_same_v<_TTuple, decay_t<_TTuple>>
3017 && is_same_v<_UTuple, decay_t<_UTuple>>
3018 && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
3019 && requires { typename __tuple_like_common_type<_TTuple, _UTuple>::type; }
3020 struct common_type<_TTuple, _UTuple>
3022 using type = typename __tuple_like_common_type<_TTuple, _UTuple>::type;
3028 #undef __glibcxx_no_dangling_refs
3030 _GLIBCXX_END_NAMESPACE_VERSION
3035 #endif // _GLIBCXX_TUPLE