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.
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>
56namespace std _GLIBCXX_VISIBILITY(default)
58_GLIBCXX_BEGIN_NAMESPACE_VERSION
61 * @addtogroup utilities
65 template<typename... _Elements>
68 /// @cond undocumented
69 template<typename _Tp>
70 struct __is_empty_non_tuple : is_empty<_Tp> { };
72 // Using EBO for elements that are tuples causes ambiguous base errors.
73 template<typename _El0, typename... _El>
74 struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { };
76 // Use the Empty Base-class Optimization for empty, non-final types.
77 template<typename _Tp>
78 using __empty_not_final
79 = __conditional_t<__is_final(_Tp), false_type,
80 __is_empty_non_tuple<_Tp>>;
82 template<size_t _Idx, typename _Head,
83 bool = __empty_not_final<_Head>::value>
86#if __has_cpp_attribute(__no_unique_address__)
87 template<size_t _Idx, typename _Head>
88 struct _Head_base<_Idx, _Head, true>
90 constexpr _Head_base()
93 constexpr _Head_base(const _Head& __h)
94 : _M_head_impl(__h) { }
96 constexpr _Head_base(const _Head_base&) = default;
97 constexpr _Head_base(_Head_base&&) = default;
99 template<typename _UHead>
100 constexpr _Head_base(_UHead&& __h)
101 : _M_head_impl(std::forward<_UHead>(__h)) { }
104 _Head_base(allocator_arg_t, __uses_alloc0)
107 template<typename _Alloc>
109 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
110 : _M_head_impl(allocator_arg, *__a._M_a) { }
112 template<typename _Alloc>
114 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
115 : _M_head_impl(*__a._M_a) { }
117 template<typename _UHead>
119 _Head_base(__uses_alloc0, _UHead&& __uhead)
120 : _M_head_impl(std::forward<_UHead>(__uhead)) { }
122 template<typename _Alloc, typename _UHead>
124 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
125 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
128 template<typename _Alloc, typename _UHead>
130 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
131 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
133 static constexpr _Head&
134 _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
136 static constexpr const _Head&
137 _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
139 [[__no_unique_address__]] _Head _M_head_impl;
142 template<size_t _Idx, typename _Head>
143 struct _Head_base<_Idx, _Head, true>
146 constexpr _Head_base()
149 constexpr _Head_base(const _Head& __h)
152 constexpr _Head_base(const _Head_base&) = default;
153 constexpr _Head_base(_Head_base&&) = default;
155 template<typename _UHead>
156 constexpr _Head_base(_UHead&& __h)
157 : _Head(std::forward<_UHead>(__h)) { }
160 _Head_base(allocator_arg_t, __uses_alloc0)
163 template<typename _Alloc>
165 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
166 : _Head(allocator_arg, *__a._M_a) { }
168 template<typename _Alloc>
170 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
171 : _Head(*__a._M_a) { }
173 template<typename _UHead>
175 _Head_base(__uses_alloc0, _UHead&& __uhead)
176 : _Head(std::forward<_UHead>(__uhead)) { }
178 template<typename _Alloc, typename _UHead>
180 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
181 : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
183 template<typename _Alloc, typename _UHead>
185 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
186 : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
188 static constexpr _Head&
189 _M_head(_Head_base& __b) noexcept { return __b; }
191 static constexpr const _Head&
192 _M_head(const _Head_base& __b) noexcept { return __b; }
196 template<size_t _Idx, typename _Head>
197 struct _Head_base<_Idx, _Head, false>
199 constexpr _Head_base()
202 constexpr _Head_base(const _Head& __h)
203 : _M_head_impl(__h) { }
205 constexpr _Head_base(const _Head_base&) = default;
206 constexpr _Head_base(_Head_base&&) = default;
208 template<typename _UHead>
209 constexpr _Head_base(_UHead&& __h)
210 : _M_head_impl(std::forward<_UHead>(__h)) { }
213 _Head_base(allocator_arg_t, __uses_alloc0)
216 template<typename _Alloc>
218 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
219 : _M_head_impl(allocator_arg, *__a._M_a) { }
221 template<typename _Alloc>
223 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
224 : _M_head_impl(*__a._M_a) { }
226 template<typename _UHead>
228 _Head_base(__uses_alloc0, _UHead&& __uhead)
229 : _M_head_impl(std::forward<_UHead>(__uhead)) { }
231 template<typename _Alloc, typename _UHead>
233 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
234 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
237 template<typename _Alloc, typename _UHead>
239 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
240 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
242 static constexpr _Head&
243 _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
245 static constexpr const _Head&
246 _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
251#if __cpp_lib_tuple_like // >= C++23
252 struct __tuple_like_tag_t { explicit __tuple_like_tag_t() = default; };
254 // These forward declarations are used by the operator<=> overload for
256 template<typename _Cat, typename _Tp, typename _Up>
258 __tuple_cmp(const _Tp&, const _Up&, index_sequence<>);
260 template<typename _Cat, typename _Tp, typename _Up,
261 size_t _Idx0, size_t... _Idxs>
263 __tuple_cmp(const _Tp& __t, const _Up& __u,
264 index_sequence<_Idx0, _Idxs...>);
268 * Contains the actual implementation of the @c tuple template, stored
269 * as a recursive inheritance hierarchy from the first element (most
270 * derived class) to the last (least derived class). The @c Idx
271 * parameter gives the 0-based index of the element stored at this
272 * point in the hierarchy; we use it to implement a constant-time
275 template<size_t _Idx, typename... _Elements>
279 * Recursive tuple implementation. Here we store the @c Head element
280 * and derive from a @c Tuple_impl containing the remaining elements
281 * (which contains the @c Tail).
283 template<size_t _Idx, typename _Head, typename... _Tail>
284 struct _Tuple_impl<_Idx, _Head, _Tail...>
285 : public _Tuple_impl<_Idx + 1, _Tail...>,
286 private _Head_base<_Idx, _Head>
288 template<size_t, typename...> friend struct _Tuple_impl;
290 typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
291 typedef _Head_base<_Idx, _Head> _Base;
293 static constexpr _Head&
294 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
296 static constexpr const _Head&
297 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
299 static constexpr _Inherited&
300 _M_tail(_Tuple_impl& __t) noexcept { return __t; }
302 static constexpr const _Inherited&
303 _M_tail(const _Tuple_impl& __t) noexcept { return __t; }
305 constexpr _Tuple_impl()
306 : _Inherited(), _Base() { }
309 _Tuple_impl(const _Head& __head, const _Tail&... __tail)
310 : _Inherited(__tail...), _Base(__head)
313 template<typename _UHead, typename... _UTail,
314 typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
316 _Tuple_impl(_UHead&& __head, _UTail&&... __tail)
317 : _Inherited(std::forward<_UTail>(__tail)...),
318 _Base(std::forward<_UHead>(__head))
321 constexpr _Tuple_impl(const _Tuple_impl&) = default;
323 // _GLIBCXX_RESOLVE_LIB_DEFECTS
324 // 2729. Missing SFINAE on std::pair::operator=
325 _Tuple_impl& operator=(const _Tuple_impl&) = delete;
327 _Tuple_impl(_Tuple_impl&&) = default;
329 template<typename... _UElements>
331 _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
332 : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
333 _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
336 template<typename _UHead, typename... _UTails>
338 _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
339 : _Inherited(std::move
340 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
341 _Base(std::forward<_UHead>
342 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
345#if __cpp_lib_ranges_zip // >= C++23
346 template<typename... _UElements>
348 _Tuple_impl(_Tuple_impl<_Idx, _UElements...>& __in)
349 : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
350 _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
353 template<typename _UHead, typename... _UTails>
355 _Tuple_impl(const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
356 : _Inherited(std::move
357 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
358 _Base(std::forward<const _UHead>
359 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
363#if __cpp_lib_tuple_like // >= C++23
364 template<typename _UTuple, size_t... _Is>
366 _Tuple_impl(__tuple_like_tag_t, _UTuple&& __u, index_sequence<_Is...>)
367 : _Tuple_impl(std::get<_Is>(std::forward<_UTuple>(__u))...)
371 template<typename _Alloc>
373 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
374 : _Inherited(__tag, __a),
375 _Base(__tag, __use_alloc<_Head>(__a))
378 template<typename _Alloc>
380 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
381 const _Head& __head, const _Tail&... __tail)
382 : _Inherited(__tag, __a, __tail...),
383 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head)
386 template<typename _Alloc, typename _UHead, typename... _UTail,
387 typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
389 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
390 _UHead&& __head, _UTail&&... __tail)
391 : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
392 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
393 std::forward<_UHead>(__head))
396 template<typename _Alloc>
398 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
399 const _Tuple_impl& __in)
400 : _Inherited(__tag, __a, _M_tail(__in)),
401 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in))
404 template<typename _Alloc>
406 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
408 : _Inherited(__tag, __a, std::move(_M_tail(__in))),
409 _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
410 std::forward<_Head>(_M_head(__in)))
413 template<typename _Alloc, typename _UHead, typename... _UTails>
415 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
416 const _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
417 : _Inherited(__tag, __a,
418 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
419 _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
420 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
423 template<typename _Alloc, typename _UHead, typename... _UTails>
425 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
426 _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
427 : _Inherited(__tag, __a, std::move
428 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
429 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
431 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
434#if __cpp_lib_ranges_zip // >= C++23
435 template<typename _Alloc, typename _UHead, typename... _UTails>
437 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
438 _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
439 : _Inherited(__tag, __a,
440 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
441 _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
442 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
445 template<typename _Alloc, typename _UHead, typename... _UTails>
447 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
448 const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
449 : _Inherited(__tag, __a, std::move
450 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
451 _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
452 std::forward<const _UHead>
453 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
457#if __cpp_lib_tuple_like // >= C++23
458 template<typename _Alloc, typename _UTuple, size_t... _Is>
460 _Tuple_impl(__tuple_like_tag_t, allocator_arg_t __tag, const _Alloc& __a,
461 _UTuple&& __u, index_sequence<_Is...>)
462 : _Tuple_impl(__tag, __a, std::get<_Is>(std::forward<_UTuple>(__u))...)
466 template<typename... _UElements>
469 _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in)
471 _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
472 _M_tail(*this)._M_assign(
473 _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
476 template<typename _UHead, typename... _UTails>
479 _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
481 _M_head(*this) = std::forward<_UHead>
482 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
483 _M_tail(*this)._M_assign(
484 std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
487#if __cpp_lib_ranges_zip // >= C++23
488 template<typename... _UElements>
490 _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) const
492 _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
493 _M_tail(*this)._M_assign(
494 _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
497 template<typename _UHead, typename... _UTails>
499 _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) const
501 _M_head(*this) = std::forward<_UHead>
502 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
503 _M_tail(*this)._M_assign(
504 std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
508#if __cpp_lib_tuple_like // >= C++23
509 template<typename _UTuple>
511 _M_assign(__tuple_like_tag_t __tag, _UTuple&& __u)
513 _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u));
514 _M_tail(*this)._M_assign(__tag, std::forward<_UTuple>(__u));
517 template<typename _UTuple>
519 _M_assign(__tuple_like_tag_t __tag, _UTuple&& __u) const
521 _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u));
522 _M_tail(*this)._M_assign(__tag, std::forward<_UTuple>(__u));
529 _M_swap(_Tuple_impl& __in)
532 swap(_M_head(*this), _M_head(__in));
533 _Inherited::_M_swap(_M_tail(__in));
536#if __cpp_lib_ranges_zip // >= C++23
538 _M_swap(const _Tuple_impl& __in) const
541 swap(_M_head(*this), _M_head(__in));
542 _Inherited::_M_swap(_M_tail(__in));
547 // Basis case of inheritance recursion.
548 template<size_t _Idx, typename _Head>
549 struct _Tuple_impl<_Idx, _Head>
550 : private _Head_base<_Idx, _Head>
552 template<size_t, typename...> friend struct _Tuple_impl;
554 typedef _Head_base<_Idx, _Head> _Base;
556 static constexpr _Head&
557 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
559 static constexpr const _Head&
560 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
567 _Tuple_impl(const _Head& __head)
571 template<typename _UHead>
573 _Tuple_impl(_UHead&& __head)
574 : _Base(std::forward<_UHead>(__head))
577 constexpr _Tuple_impl(const _Tuple_impl&) = default;
579 // _GLIBCXX_RESOLVE_LIB_DEFECTS
580 // 2729. Missing SFINAE on std::pair::operator=
581 _Tuple_impl& operator=(const _Tuple_impl&) = delete;
583#if _GLIBCXX_INLINE_VERSION
584 _Tuple_impl(_Tuple_impl&&) = default;
587 _Tuple_impl(_Tuple_impl&& __in)
588 noexcept(is_nothrow_move_constructible<_Head>::value)
589 : _Base(static_cast<_Base&&>(__in))
593 template<typename _UHead>
595 _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in)
596 : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
599 template<typename _UHead>
601 _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in)
602 : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
605#if __cpp_lib_ranges_zip // >= C++23
606 template<typename _UHead>
608 _Tuple_impl(_Tuple_impl<_Idx, _UHead>& __in)
609 : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
612 template<typename _UHead>
614 _Tuple_impl(const _Tuple_impl<_Idx, _UHead>&& __in)
615 : _Base(std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
619#if __cpp_lib_tuple_like // >= C++23
620 template<typename _UTuple>
622 _Tuple_impl(__tuple_like_tag_t, _UTuple&& __u, index_sequence<0>)
623 : _Tuple_impl(std::get<0>(std::forward<_UTuple>(__u)))
627 template<typename _Alloc>
629 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
630 : _Base(__tag, __use_alloc<_Head>(__a))
633 template<typename _Alloc>
635 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
637 : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), __head)
640 template<typename _Alloc, typename _UHead>
642 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
644 : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
645 std::forward<_UHead>(__head))
648 template<typename _Alloc>
650 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
651 const _Tuple_impl& __in)
652 : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), _M_head(__in))
655 template<typename _Alloc>
657 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
659 : _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
660 std::forward<_Head>(_M_head(__in)))
663 template<typename _Alloc, typename _UHead>
665 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
666 const _Tuple_impl<_Idx, _UHead>& __in)
667 : _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
668 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
671 template<typename _Alloc, typename _UHead>
673 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
674 _Tuple_impl<_Idx, _UHead>&& __in)
675 : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
676 std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
679#if __cpp_lib_ranges_zip // >= C++23
680 template<typename _Alloc, typename _UHead>
682 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
683 _Tuple_impl<_Idx, _UHead>& __in)
684 : _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
685 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
688 template<typename _Alloc, typename _UHead>
690 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
691 const _Tuple_impl<_Idx, _UHead>&& __in)
692 : _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
693 std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
697#if __cpp_lib_tuple_like // >= C++23
698 template<typename _Alloc, typename _UTuple>
700 _Tuple_impl(__tuple_like_tag_t, allocator_arg_t __tag, const _Alloc& __a,
701 _UTuple&& __u, index_sequence<0>)
702 : _Tuple_impl(__tag, __a, std::get<0>(std::forward<_UTuple>(__u)))
706 template<typename _UHead>
709 _M_assign(const _Tuple_impl<_Idx, _UHead>& __in)
711 _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
714 template<typename _UHead>
717 _M_assign(_Tuple_impl<_Idx, _UHead>&& __in)
720 = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
723#if __cpp_lib_ranges_zip // >= C++23
724 template<typename _UHead>
726 _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) const
728 _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
731 template<typename _UHead>
733 _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) const
736 = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
740#if __cpp_lib_tuple_like // >= C++23
741 template<typename _UTuple>
743 _M_assign(__tuple_like_tag_t, _UTuple&& __u)
744 { _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); }
746 template<typename _UTuple>
748 _M_assign(__tuple_like_tag_t, _UTuple&& __u) const
749 { _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); }
755 _M_swap(_Tuple_impl& __in)
758 swap(_M_head(*this), _M_head(__in));
761#if __cpp_lib_ranges_zip // >= C++23
763 _M_swap(const _Tuple_impl& __in) const
766 swap(_M_head(*this), _M_head(__in));
771 // Concept utility functions, reused in conditionally-explicit
773 template<bool, typename... _Types>
774 struct _TupleConstraints
776 template<typename... _UTypes>
777 using __constructible = __and_<is_constructible<_Types, _UTypes>...>;
779 template<typename... _UTypes>
780 using __convertible = __and_<is_convertible<_UTypes, _Types>...>;
782 // Constraint for a non-explicit constructor.
783 // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
784 // and every Ui is implicitly convertible to Ti.
785 template<typename... _UTypes>
786 static constexpr bool __is_implicitly_constructible()
788 return __and_<__constructible<_UTypes...>,
789 __convertible<_UTypes...>
793 // Constraint for a non-explicit constructor.
794 // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
795 // but not every Ui is implicitly convertible to Ti.
796 template<typename... _UTypes>
797 static constexpr bool __is_explicitly_constructible()
799 return __and_<__constructible<_UTypes...>,
800 __not_<__convertible<_UTypes...>>
804 static constexpr bool __is_implicitly_default_constructible()
806 return __and_<std::__is_implicitly_default_constructible<_Types>...
810 static constexpr bool __is_explicitly_default_constructible()
812 return __and_<is_default_constructible<_Types>...,
814 std::__is_implicitly_default_constructible<_Types>...>
819 // Partial specialization used when a required precondition isn't met,
820 // e.g. when sizeof...(_Types) != sizeof...(_UTypes).
821 template<typename... _Types>
822 struct _TupleConstraints<false, _Types...>
824 template<typename... _UTypes>
825 static constexpr bool __is_implicitly_constructible()
828 template<typename... _UTypes>
829 static constexpr bool __is_explicitly_constructible()
834 /// Primary class template, tuple
835 template<typename... _Elements>
836 class tuple : public _Tuple_impl<0, _Elements...>
838 using _Inherited = _Tuple_impl<0, _Elements...>;
840#if __cpp_concepts && __cpp_consteval && __cpp_conditional_explicit // >= C++20
841 template<typename... _UTypes>
842 static consteval bool
845 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
846 return __and_v<is_constructible<_Elements, _UTypes>...>;
851 template<typename... _UTypes>
852 static consteval bool
853 __nothrow_constructible()
855 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
856 return __and_v<is_nothrow_constructible<_Elements, _UTypes>...>;
861 template<typename... _UTypes>
862 static consteval bool
865 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
866 return __and_v<is_convertible<_UTypes, _Elements>...>;
871 // _GLIBCXX_RESOLVE_LIB_DEFECTS
872 // 3121. tuple constructor constraints for UTypes&&... overloads
873 template<typename... _UTypes>
874 static consteval bool
875 __disambiguating_constraint()
877 if constexpr (sizeof...(_Elements) != sizeof...(_UTypes))
879 else if constexpr (sizeof...(_Elements) == 1)
881 using _U0 = typename _Nth_type<0, _UTypes...>::type;
882 return !is_same_v<remove_cvref_t<_U0>, tuple>;
884 else if constexpr (sizeof...(_Elements) < 4)
886 using _U0 = typename _Nth_type<0, _UTypes...>::type;
887 if constexpr (!is_same_v<remove_cvref_t<_U0>, allocator_arg_t>)
891 using _T0 = typename _Nth_type<0, _Elements...>::type;
892 return is_same_v<remove_cvref_t<_T0>, allocator_arg_t>;
898 // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
899 // and the single element in Types can be initialized from TUPLE,
900 // or is the same type as tuple_element_t<0, TUPLE>.
901 template<typename _Tuple>
902 static consteval bool
905 if constexpr (sizeof...(_Elements) != 1)
907 else if constexpr (is_same_v<remove_cvref_t<_Tuple>, tuple>)
908 return true; // Should use a copy/move constructor instead.
911 using _Tp = typename _Nth_type<0, _Elements...>::type;
912 if constexpr (is_convertible_v<_Tuple, _Tp>)
914 else if constexpr (is_constructible_v<_Tp, _Tuple>)
920 template<typename... _Up>
921 static consteval bool
924#if __has_builtin(__reference_constructs_from_temporary)
925 return (__reference_constructs_from_temporary(_Elements, _Up&&)
932#if __cpp_lib_tuple_like // >= C++23
933 // _GLIBCXX_RESOLVE_LIB_DEFECTS
934 // 4045. tuple can create dangling references from tuple-like
935 template<typename _UTuple>
936 static consteval bool
937 __dangles_from_tuple_like()
939 return []<size_t... _Is>(index_sequence<_Is...>) {
940 return __dangles<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
941 }(index_sequence_for<_Elements...>{});
944 template<typename _UTuple>
945 static consteval bool
946 __constructible_from_tuple_like()
948 return []<size_t... _Is>(index_sequence<_Is...>) {
949 return __constructible<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
950 }(index_sequence_for<_Elements...>{});
953 template<typename _UTuple>
954 static consteval bool
955 __convertible_from_tuple_like()
957 return []<size_t... _Is>(index_sequence<_Is...>) {
958 return __convertible<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
959 }(index_sequence_for<_Elements...>{});
965 explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
967 noexcept((is_nothrow_default_constructible_v<_Elements> && ...))
968 requires (is_default_constructible_v<_Elements> && ...)
972 constexpr explicit(!__convertible<const _Elements&...>())
973 tuple(const _Elements&... __elements)
974 noexcept(__nothrow_constructible<const _Elements&...>())
975 requires (__constructible<const _Elements&...>())
976 : _Inherited(__elements...)
979 template<typename... _UTypes>
980 requires (__disambiguating_constraint<_UTypes...>())
981 && (__constructible<_UTypes...>())
982 && (!__dangles<_UTypes...>())
983 constexpr explicit(!__convertible<_UTypes...>())
984 tuple(_UTypes&&... __u)
985 noexcept(__nothrow_constructible<_UTypes...>())
986 : _Inherited(std::forward<_UTypes>(__u)...)
989 template<typename... _UTypes>
990 requires (__disambiguating_constraint<_UTypes...>())
991 && (__constructible<_UTypes...>())
992 && (__dangles<_UTypes...>())
993 tuple(_UTypes&&...) = delete;
995 constexpr tuple(const tuple&) = default;
997 constexpr tuple(tuple&&) = default;
999 template<typename... _UTypes>
1000 requires (__constructible<const _UTypes&...>())
1001 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1002 && (!__dangles<const _UTypes&...>())
1003 constexpr explicit(!__convertible<const _UTypes&...>())
1004 tuple(const tuple<_UTypes...>& __u)
1005 noexcept(__nothrow_constructible<const _UTypes&...>())
1006 : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1009 template<typename... _UTypes>
1010 requires (__constructible<const _UTypes&...>())
1011 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1012 && (__dangles<const _UTypes&...>())
1013 tuple(const tuple<_UTypes...>&) = delete;
1015 template<typename... _UTypes>
1016 requires (__constructible<_UTypes...>())
1017 && (!__use_other_ctor<tuple<_UTypes...>>())
1018 && (!__dangles<_UTypes...>())
1019 constexpr explicit(!__convertible<_UTypes...>())
1020 tuple(tuple<_UTypes...>&& __u)
1021 noexcept(__nothrow_constructible<_UTypes...>())
1022 : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1025 template<typename... _UTypes>
1026 requires (__constructible<_UTypes...>())
1027 && (!__use_other_ctor<tuple<_UTypes...>>())
1028 && (__dangles<_UTypes...>())
1029 tuple(tuple<_UTypes...>&&) = delete;
1031#if __cpp_lib_ranges_zip // >= C++23
1032 template<typename... _UTypes>
1033 requires (__constructible<_UTypes&...>())
1034 && (!__use_other_ctor<tuple<_UTypes...>&>())
1035 && (!__dangles<_UTypes&...>())
1036 constexpr explicit(!__convertible<_UTypes&...>())
1037 tuple(tuple<_UTypes...>& __u)
1038 noexcept(__nothrow_constructible<_UTypes&...>())
1039 : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1042 template<typename... _UTypes>
1043 requires (__constructible<_UTypes&...>())
1044 && (!__use_other_ctor<tuple<_UTypes...>&>())
1045 && (__dangles<_UTypes&...>())
1046 tuple(tuple<_UTypes...>&) = delete;
1048 template<typename... _UTypes>
1049 requires (__constructible<const _UTypes...>())
1050 && (!__use_other_ctor<const tuple<_UTypes...>>())
1051 && (!__dangles<const _UTypes...>())
1052 constexpr explicit(!__convertible<const _UTypes...>())
1053 tuple(const tuple<_UTypes...>&& __u)
1054 noexcept(__nothrow_constructible<const _UTypes...>())
1055 : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1058 template<typename... _UTypes>
1059 requires (__constructible<const _UTypes...>())
1060 && (!__use_other_ctor<const tuple<_UTypes...>>())
1061 && (__dangles<const _UTypes...>())
1062 tuple(const tuple<_UTypes...>&&) = delete;
1065 template<typename _U1, typename _U2>
1066 requires (sizeof...(_Elements) == 2)
1067 && (__constructible<const _U1&, const _U2&>())
1068 && (!__dangles<const _U1&, const _U2&>())
1069 constexpr explicit(!__convertible<const _U1&, const _U2&>())
1070 tuple(const pair<_U1, _U2>& __u)
1071 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1072 : _Inherited(__u.first, __u.second)
1075 template<typename _U1, typename _U2>
1076 requires (sizeof...(_Elements) == 2)
1077 && (__constructible<const _U1&, const _U2&>())
1078 && (__dangles<const _U1&, const _U2&>())
1079 tuple(const pair<_U1, _U2>&) = delete;
1081 template<typename _U1, typename _U2>
1082 requires (sizeof...(_Elements) == 2)
1083 && (__constructible<_U1, _U2>())
1084 && (!__dangles<_U1, _U2>())
1085 constexpr explicit(!__convertible<_U1, _U2>())
1086 tuple(pair<_U1, _U2>&& __u)
1087 noexcept(__nothrow_constructible<_U1, _U2>())
1088 : _Inherited(std::forward<_U1>(__u.first),
1089 std::forward<_U2>(__u.second))
1092 template<typename _U1, typename _U2>
1093 requires (sizeof...(_Elements) == 2)
1094 && (__constructible<_U1, _U2>())
1095 && (__dangles<_U1, _U2>())
1096 tuple(pair<_U1, _U2>&&) = delete;
1098#if __cpp_lib_ranges_zip // >= C++23
1099 template<typename _U1, typename _U2>
1100 requires (sizeof...(_Elements) == 2)
1101 && (__constructible<_U1&, _U2&>())
1102 && (!__dangles<_U1&, _U2&>())
1103 constexpr explicit(!__convertible<_U1&, _U2&>())
1104 tuple(pair<_U1, _U2>& __u)
1105 noexcept(__nothrow_constructible<_U1&, _U2&>())
1106 : _Inherited(__u.first, __u.second)
1109 template<typename _U1, typename _U2>
1110 requires (sizeof...(_Elements) == 2)
1111 && (__constructible<_U1&, _U2&>())
1112 && (__dangles<_U1&, _U2&>())
1113 tuple(pair<_U1, _U2>&) = delete;
1115 template<typename _U1, typename _U2>
1116 requires (sizeof...(_Elements) == 2)
1117 && (__constructible<const _U1, const _U2>())
1118 && (!__dangles<const _U1, const _U2>())
1119 constexpr explicit(!__convertible<const _U1, const _U2>())
1120 tuple(const pair<_U1, _U2>&& __u)
1121 noexcept(__nothrow_constructible<const _U1, const _U2>())
1122 : _Inherited(std::forward<const _U1>(__u.first),
1123 std::forward<const _U2>(__u.second))
1126 template<typename _U1, typename _U2>
1127 requires (sizeof...(_Elements) == 2)
1128 && (__constructible<const _U1, const _U2>())
1129 && (__dangles<const _U1, const _U2>())
1130 tuple(const pair<_U1, _U2>&&) = delete;
1133#if __cpp_lib_tuple_like // >= C++23
1134 template<__eligible_tuple_like<tuple> _UTuple>
1135 requires (__constructible_from_tuple_like<_UTuple>())
1136 && (!__use_other_ctor<_UTuple>())
1137 && (!__dangles_from_tuple_like<_UTuple>())
1138 constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
1139 tuple(_UTuple&& __u)
1140 : _Inherited(__tuple_like_tag_t{},
1141 std::forward<_UTuple>(__u),
1142 index_sequence_for<_Elements...>{})
1145 template<__eligible_tuple_like<tuple> _UTuple>
1146 requires (__constructible_from_tuple_like<_UTuple>())
1147 && (!__use_other_ctor<_UTuple>())
1148 && (__dangles_from_tuple_like<_UTuple>())
1149 tuple(_UTuple&&) = delete;
1152 // Allocator-extended constructors.
1154 template<typename _Alloc>
1156 explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
1157 tuple(allocator_arg_t __tag, const _Alloc& __a)
1158 requires (is_default_constructible_v<_Elements> && ...)
1159 : _Inherited(__tag, __a)
1162 template<typename _Alloc>
1163 constexpr explicit(!__convertible<const _Elements&...>())
1164 tuple(allocator_arg_t __tag, const _Alloc& __a,
1165 const _Elements&... __elements)
1166 requires (__constructible<const _Elements&...>())
1167 : _Inherited(__tag, __a, __elements...)
1170 template<typename _Alloc, typename... _UTypes>
1171 requires (__disambiguating_constraint<_UTypes...>())
1172 && (__constructible<_UTypes...>())
1173 && (!__dangles<_UTypes...>())
1174 constexpr explicit(!__convertible<_UTypes...>())
1175 tuple(allocator_arg_t __tag, const _Alloc& __a, _UTypes&&... __u)
1176 : _Inherited(__tag, __a, std::forward<_UTypes>(__u)...)
1179 template<typename _Alloc, typename... _UTypes>
1180 requires (__disambiguating_constraint<_UTypes...>())
1181 && (__constructible<_UTypes...>())
1182 && (__dangles<_UTypes...>())
1183 tuple(allocator_arg_t, const _Alloc&, _UTypes&&...) = delete;
1185 template<typename _Alloc>
1187 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __u)
1188 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__u))
1191 template<typename _Alloc>
1192 requires (__constructible<_Elements...>())
1194 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __u)
1195 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__u))
1198 template<typename _Alloc, typename... _UTypes>
1199 requires (__constructible<const _UTypes&...>())
1200 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1201 && (!__dangles<const _UTypes&...>())
1202 constexpr explicit(!__convertible<const _UTypes&...>())
1203 tuple(allocator_arg_t __tag, const _Alloc& __a,
1204 const tuple<_UTypes...>& __u)
1205 : _Inherited(__tag, __a,
1206 static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1209 template<typename _Alloc, typename... _UTypes>
1210 requires (__constructible<const _UTypes&...>())
1211 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1212 && (__dangles<const _UTypes&...>())
1213 tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&) = delete;
1215 template<typename _Alloc, typename... _UTypes>
1216 requires (__constructible<_UTypes...>())
1217 && (!__use_other_ctor<tuple<_UTypes...>>())
1218 && (!__dangles<_UTypes...>())
1219 constexpr explicit(!__use_other_ctor<tuple<_UTypes...>>())
1220 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>&& __u)
1221 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1224 template<typename _Alloc, typename... _UTypes>
1225 requires (__constructible<_UTypes...>())
1226 && (!__use_other_ctor<tuple<_UTypes...>>())
1227 && (__dangles<_UTypes...>())
1228 tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&&) = delete;
1230#if __cpp_lib_ranges_zip // >= C++23
1231 template<typename _Alloc, typename... _UTypes>
1232 requires (__constructible<_UTypes&...>())
1233 && (!__use_other_ctor<tuple<_UTypes...>&>())
1234 && (!__dangles<_UTypes&...>())
1235 constexpr explicit(!__convertible<_UTypes&...>())
1236 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>& __u)
1237 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1240 template<typename _Alloc, typename... _UTypes>
1241 requires (__constructible<_UTypes&...>())
1242 && (!__use_other_ctor<tuple<_UTypes...>&>())
1243 && (__dangles<_UTypes&...>())
1244 tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&) = delete;
1246 template<typename _Alloc, typename... _UTypes>
1247 requires (__constructible<const _UTypes...>())
1248 && (!__use_other_ctor<const tuple<_UTypes...>>())
1249 && (!__dangles<const _UTypes...>())
1250 constexpr explicit(!__convertible<const _UTypes...>())
1251 tuple(allocator_arg_t __tag, const _Alloc& __a,
1252 const tuple<_UTypes...>&& __u)
1253 : _Inherited(__tag, __a,
1254 static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1257 template<typename _Alloc, typename... _UTypes>
1258 requires (__constructible<const _UTypes...>())
1259 && (!__use_other_ctor<const tuple<_UTypes...>>())
1260 && (__dangles<const _UTypes...>())
1261 tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&&) = delete;
1264 template<typename _Alloc, typename _U1, typename _U2>
1265 requires (sizeof...(_Elements) == 2)
1266 && (__constructible<const _U1&, const _U2&>())
1267 && (!__dangles<const _U1&, const _U2&>())
1268 constexpr explicit(!__convertible<const _U1&, const _U2&>())
1269 tuple(allocator_arg_t __tag, const _Alloc& __a,
1270 const pair<_U1, _U2>& __u)
1271 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1272 : _Inherited(__tag, __a, __u.first, __u.second)
1275 template<typename _Alloc, typename _U1, typename _U2>
1276 requires (sizeof...(_Elements) == 2)
1277 && (__constructible<const _U1&, const _U2&>())
1278 && (__dangles<const _U1&, const _U2&>())
1279 tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&) = delete;
1281 template<typename _Alloc, typename _U1, typename _U2>
1282 requires (sizeof...(_Elements) == 2)
1283 && (__constructible<_U1, _U2>())
1284 && (!__dangles<_U1, _U2>())
1285 constexpr explicit(!__convertible<_U1, _U2>())
1286 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __u)
1287 noexcept(__nothrow_constructible<_U1, _U2>())
1288 : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1291 template<typename _Alloc, typename _U1, typename _U2>
1292 requires (sizeof...(_Elements) == 2)
1293 && (__constructible<_U1, _U2>())
1294 && (__dangles<_U1, _U2>())
1295 tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&) = delete;
1297#if __cpp_lib_ranges_zip // >= C++23
1298 template<typename _Alloc, typename _U1, typename _U2>
1299 requires (sizeof...(_Elements) == 2)
1300 && (__constructible<_U1&, _U2&>())
1301 && (!__dangles<_U1&, _U2&>())
1302 constexpr explicit(!__convertible<_U1&, _U2&>())
1303 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>& __u)
1304 noexcept(__nothrow_constructible<_U1&, _U2&>())
1305 : _Inherited(__tag, __a, __u.first, __u.second)
1308 template<typename _Alloc, typename _U1, typename _U2>
1309 requires (sizeof...(_Elements) == 2)
1310 && (__constructible<_U1&, _U2&>())
1311 && (__dangles<_U1&, _U2&>())
1312 tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&) = delete;
1314 template<typename _Alloc, typename _U1, typename _U2>
1315 requires (sizeof...(_Elements) == 2)
1316 && (__constructible<const _U1, const _U2>())
1317 && (!__dangles<const _U1, const _U2>())
1318 constexpr explicit(!__convertible<const _U1, const _U2>())
1319 tuple(allocator_arg_t __tag, const _Alloc& __a,
1320 const pair<_U1, _U2>&& __u)
1321 noexcept(__nothrow_constructible<const _U1, const _U2>())
1322 : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1325 template<typename _Alloc, typename _U1, typename _U2>
1326 requires (sizeof...(_Elements) == 2)
1327 && (__constructible<const _U1, const _U2>())
1328 && (__dangles<const _U1, const _U2>())
1329 tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&&) = delete;
1332#if __cpp_lib_tuple_like // >= C++23
1333 template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
1334 requires (__constructible_from_tuple_like<_UTuple>())
1335 && (!__use_other_ctor<_UTuple>())
1336 && (!__dangles_from_tuple_like<_UTuple>())
1337 constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
1338 tuple(allocator_arg_t __tag, const _Alloc& __a, _UTuple&& __u)
1339 : _Inherited(__tuple_like_tag_t{},
1340 __tag, __a, std::forward<_UTuple>(__u),
1341 index_sequence_for<_Elements...>{})
1344 template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
1345 requires (__constructible_from_tuple_like<_UTuple>())
1346 && (!__use_other_ctor<_UTuple>())
1347 && (__dangles_from_tuple_like<_UTuple>())
1348 tuple(allocator_arg_t, const _Alloc&, _UTuple&&) = delete;
1351#else // !(concepts && conditional_explicit)
1353 template<bool _Cond>
1354 using _TCC = _TupleConstraints<_Cond, _Elements...>;
1356 // Constraint for non-explicit default constructor
1357 template<bool _Dummy>
1358 using _ImplicitDefaultCtor = __enable_if_t<
1359 _TCC<_Dummy>::__is_implicitly_default_constructible(),
1362 // Constraint for explicit default constructor
1363 template<bool _Dummy>
1364 using _ExplicitDefaultCtor = __enable_if_t<
1365 _TCC<_Dummy>::__is_explicitly_default_constructible(),
1368 // Constraint for non-explicit constructors
1369 template<bool _Cond, typename... _Args>
1370 using _ImplicitCtor = __enable_if_t<
1371 _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
1374 // Constraint for non-explicit constructors
1375 template<bool _Cond, typename... _Args>
1376 using _ExplicitCtor = __enable_if_t<
1377 _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
1380 // Condition for noexcept-specifier of a constructor.
1381 template<typename... _UElements>
1382 static constexpr bool __nothrow_constructible()
1385 __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
1388 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1.
1389 template<typename _Up>
1390 static constexpr bool __valid_args()
1392 return sizeof...(_Elements) == 1
1393 && !is_same<tuple, __remove_cvref_t<_Up>>::value;
1396 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1.
1397 template<typename, typename, typename... _Tail>
1398 static constexpr bool __valid_args()
1399 { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); }
1401 /* Constraint for constructors with a tuple<UTypes...> parameter ensures
1402 * that the constructor is only viable when it would not interfere with
1403 * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&).
1404 * Such constructors are only viable if:
1405 * either sizeof...(Types) != 1,
1406 * or (when Types... expands to T and UTypes... expands to U)
1407 * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>,
1408 * and is_same_v<T, U> are all false.
1410 template<typename _Tuple, typename = tuple,
1411 typename = __remove_cvref_t<_Tuple>>
1412 struct _UseOtherCtor
1415 // If TUPLE is convertible to the single element in *this,
1416 // then TUPLE should match tuple(UTypes&&...) instead.
1417 template<typename _Tuple, typename _Tp, typename _Up>
1418 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>>
1419 : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>::type
1421 // If TUPLE and *this each have a single element of the same type,
1422 // then TUPLE should match a copy/move constructor instead.
1423 template<typename _Tuple, typename _Tp>
1424 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>>
1428 // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
1429 // and the single element in Types can be initialized from TUPLE,
1430 // or is the same type as tuple_element_t<0, TUPLE>.
1431 template<typename _Tuple>
1432 static constexpr bool __use_other_ctor()
1433 { return _UseOtherCtor<_Tuple>::value; }
1435 /// @cond undocumented
1436#undef __glibcxx_no_dangling_refs
1437#if __has_builtin(__reference_constructs_from_temporary) \
1438 && defined _GLIBCXX_DEBUG
1439 // Error if construction from U... would create a dangling ref.
1440# if __cpp_fold_expressions
1441# define __glibcxx_dangling_refs(U) \
1442 (__reference_constructs_from_temporary(_Elements, U) || ...)
1444# define __glibcxx_dangling_refs(U) \
1445 __or_<__bool_constant<__reference_constructs_from_temporary(_Elements, U) \
1448# define __glibcxx_no_dangling_refs(U) \
1449 static_assert(!__glibcxx_dangling_refs(U), \
1450 "std::tuple constructor creates a dangling reference")
1452# define __glibcxx_no_dangling_refs(U)
1457 template<typename _Dummy = void,
1458 _ImplicitDefaultCtor<is_void<_Dummy>::value> = true>
1461 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1464 template<typename _Dummy = void,
1465 _ExplicitDefaultCtor<is_void<_Dummy>::value> = false>
1468 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1471 template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1472 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1474 tuple(const _Elements&... __elements)
1475 noexcept(__nothrow_constructible<const _Elements&...>())
1476 : _Inherited(__elements...) { }
1478 template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1479 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1481 tuple(const _Elements&... __elements)
1482 noexcept(__nothrow_constructible<const _Elements&...>())
1483 : _Inherited(__elements...) { }
1485 template<typename... _UElements,
1486 bool _Valid = __valid_args<_UElements...>(),
1487 _ImplicitCtor<_Valid, _UElements...> = true>
1489 tuple(_UElements&&... __elements)
1490 noexcept(__nothrow_constructible<_UElements...>())
1491 : _Inherited(std::forward<_UElements>(__elements)...)
1492 { __glibcxx_no_dangling_refs(_UElements&&); }
1494 template<typename... _UElements,
1495 bool _Valid = __valid_args<_UElements...>(),
1496 _ExplicitCtor<_Valid, _UElements...> = false>
1498 tuple(_UElements&&... __elements)
1499 noexcept(__nothrow_constructible<_UElements...>())
1500 : _Inherited(std::forward<_UElements>(__elements)...)
1501 { __glibcxx_no_dangling_refs(_UElements&&); }
1503 constexpr tuple(const tuple&) = default;
1505 constexpr tuple(tuple&&) = default;
1507 template<typename... _UElements,
1508 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1509 && !__use_other_ctor<const tuple<_UElements...>&>(),
1510 _ImplicitCtor<_Valid, const _UElements&...> = true>
1512 tuple(const tuple<_UElements...>& __in)
1513 noexcept(__nothrow_constructible<const _UElements&...>())
1514 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1515 { __glibcxx_no_dangling_refs(const _UElements&); }
1517 template<typename... _UElements,
1518 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1519 && !__use_other_ctor<const tuple<_UElements...>&>(),
1520 _ExplicitCtor<_Valid, const _UElements&...> = false>
1522 tuple(const tuple<_UElements...>& __in)
1523 noexcept(__nothrow_constructible<const _UElements&...>())
1524 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1525 { __glibcxx_no_dangling_refs(const _UElements&); }
1527 template<typename... _UElements,
1528 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1529 && !__use_other_ctor<tuple<_UElements...>&&>(),
1530 _ImplicitCtor<_Valid, _UElements...> = true>
1532 tuple(tuple<_UElements...>&& __in)
1533 noexcept(__nothrow_constructible<_UElements...>())
1534 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1535 { __glibcxx_no_dangling_refs(_UElements&&); }
1537 template<typename... _UElements,
1538 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1539 && !__use_other_ctor<tuple<_UElements...>&&>(),
1540 _ExplicitCtor<_Valid, _UElements...> = false>
1542 tuple(tuple<_UElements...>&& __in)
1543 noexcept(__nothrow_constructible<_UElements...>())
1544 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1545 { __glibcxx_no_dangling_refs(_UElements&&); }
1547 // Allocator-extended constructors.
1549 template<typename _Alloc,
1550 _ImplicitDefaultCtor<is_object<_Alloc>::value> = true>
1551 _GLIBCXX20_CONSTEXPR
1552 tuple(allocator_arg_t __tag, const _Alloc& __a)
1553 : _Inherited(__tag, __a) { }
1555 template<typename _Alloc,
1556 _ExplicitDefaultCtor<is_object<_Alloc>::value> = false>
1557 _GLIBCXX20_CONSTEXPR
1559 tuple(allocator_arg_t __tag, const _Alloc& __a)
1560 : _Inherited(__tag, __a) { }
1562 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1563 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1564 _GLIBCXX20_CONSTEXPR
1565 tuple(allocator_arg_t __tag, const _Alloc& __a,
1566 const _Elements&... __elements)
1567 : _Inherited(__tag, __a, __elements...) { }
1569 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1570 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1571 _GLIBCXX20_CONSTEXPR
1573 tuple(allocator_arg_t __tag, const _Alloc& __a,
1574 const _Elements&... __elements)
1575 : _Inherited(__tag, __a, __elements...) { }
1577 template<typename _Alloc, typename... _UElements,
1578 bool _Valid = __valid_args<_UElements...>(),
1579 _ImplicitCtor<_Valid, _UElements...> = true>
1580 _GLIBCXX20_CONSTEXPR
1581 tuple(allocator_arg_t __tag, const _Alloc& __a,
1582 _UElements&&... __elements)
1583 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1584 { __glibcxx_no_dangling_refs(_UElements&&); }
1586 template<typename _Alloc, typename... _UElements,
1587 bool _Valid = __valid_args<_UElements...>(),
1588 _ExplicitCtor<_Valid, _UElements...> = false>
1589 _GLIBCXX20_CONSTEXPR
1591 tuple(allocator_arg_t __tag, const _Alloc& __a,
1592 _UElements&&... __elements)
1593 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1594 { __glibcxx_no_dangling_refs(_UElements&&); }
1596 template<typename _Alloc>
1597 _GLIBCXX20_CONSTEXPR
1598 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1599 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1601 template<typename _Alloc>
1602 _GLIBCXX20_CONSTEXPR
1603 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1604 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1606 template<typename _Alloc, typename... _UElements,
1607 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1608 && !__use_other_ctor<const tuple<_UElements...>&>(),
1609 _ImplicitCtor<_Valid, const _UElements&...> = true>
1610 _GLIBCXX20_CONSTEXPR
1611 tuple(allocator_arg_t __tag, const _Alloc& __a,
1612 const tuple<_UElements...>& __in)
1613 : _Inherited(__tag, __a,
1614 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1615 { __glibcxx_no_dangling_refs(const _UElements&); }
1617 template<typename _Alloc, typename... _UElements,
1618 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1619 && !__use_other_ctor<const tuple<_UElements...>&>(),
1620 _ExplicitCtor<_Valid, const _UElements&...> = false>
1621 _GLIBCXX20_CONSTEXPR
1623 tuple(allocator_arg_t __tag, const _Alloc& __a,
1624 const tuple<_UElements...>& __in)
1625 : _Inherited(__tag, __a,
1626 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1627 { __glibcxx_no_dangling_refs(const _UElements&); }
1629 template<typename _Alloc, typename... _UElements,
1630 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1631 && !__use_other_ctor<tuple<_UElements...>&&>(),
1632 _ImplicitCtor<_Valid, _UElements...> = true>
1633 _GLIBCXX20_CONSTEXPR
1634 tuple(allocator_arg_t __tag, const _Alloc& __a,
1635 tuple<_UElements...>&& __in)
1636 : _Inherited(__tag, __a,
1637 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1638 { __glibcxx_no_dangling_refs(_UElements&&); }
1640 template<typename _Alloc, typename... _UElements,
1641 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1642 && !__use_other_ctor<tuple<_UElements...>&&>(),
1643 _ExplicitCtor<_Valid, _UElements...> = false>
1644 _GLIBCXX20_CONSTEXPR
1646 tuple(allocator_arg_t __tag, const _Alloc& __a,
1647 tuple<_UElements...>&& __in)
1648 : _Inherited(__tag, __a,
1649 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1650 { __glibcxx_no_dangling_refs(_UElements&&); }
1651#endif // concepts && conditional_explicit
1655#if __cpp_concepts && __cpp_consteval // >= C++20
1657 template<typename... _UTypes>
1658 static consteval bool
1661 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1662 return __and_v<is_assignable<_Elements&, _UTypes>...>;
1667 template<typename... _UTypes>
1668 static consteval bool
1669 __nothrow_assignable()
1671 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1672 return __and_v<is_nothrow_assignable<_Elements&, _UTypes>...>;
1677#if __cpp_lib_ranges_zip // >= C++23
1678 template<typename... _UTypes>
1679 static consteval bool
1680 __const_assignable()
1682 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1683 return __and_v<is_assignable<const _Elements&, _UTypes>...>;
1689#if __cpp_lib_tuple_like // >= C++23
1690 template<typename _UTuple>
1691 static consteval bool
1692 __assignable_from_tuple_like()
1694 return []<size_t... _Is>(index_sequence<_Is...>) {
1695 return __assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1696 }(index_sequence_for<_Elements...>{});
1699 template<typename _UTuple>
1700 static consteval bool
1701 __const_assignable_from_tuple_like()
1703 return []<size_t... _Is>(index_sequence<_Is...>) {
1704 return __const_assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1705 }(index_sequence_for<_Elements...>{});
1711 tuple& operator=(const tuple& __u) = delete;
1714 operator=(const tuple& __u)
1715 noexcept(__nothrow_assignable<const _Elements&...>())
1716 requires (__assignable<const _Elements&...>())
1718 this->_M_assign(__u);
1723 operator=(tuple&& __u)
1724 noexcept(__nothrow_assignable<_Elements...>())
1725 requires (__assignable<_Elements...>())
1727 this->_M_assign(std::move(__u));
1731 template<typename... _UTypes>
1732 requires (__assignable<const _UTypes&...>())
1734 operator=(const tuple<_UTypes...>& __u)
1735 noexcept(__nothrow_assignable<const _UTypes&...>())
1737 this->_M_assign(__u);
1741 template<typename... _UTypes>
1742 requires (__assignable<_UTypes...>())
1744 operator=(tuple<_UTypes...>&& __u)
1745 noexcept(__nothrow_assignable<_UTypes...>())
1747 this->_M_assign(std::move(__u));
1751#if __cpp_lib_ranges_zip // >= C++23
1752 constexpr const tuple&
1753 operator=(const tuple& __u) const
1754 requires (__const_assignable<const _Elements&...>())
1756 this->_M_assign(__u);
1760 constexpr const tuple&
1761 operator=(tuple&& __u) const
1762 requires (__const_assignable<_Elements...>())
1764 this->_M_assign(std::move(__u));
1768 template<typename... _UTypes>
1769 constexpr const tuple&
1770 operator=(const tuple<_UTypes...>& __u) const
1771 requires (__const_assignable<const _UTypes&...>())
1773 this->_M_assign(__u);
1777 template<typename... _UTypes>
1778 constexpr const tuple&
1779 operator=(tuple<_UTypes...>&& __u) const
1780 requires (__const_assignable<_UTypes...>())
1782 this->_M_assign(std::move(__u));
1787 template<typename _U1, typename _U2>
1788 requires (__assignable<const _U1&, const _U2&>())
1790 operator=(const pair<_U1, _U2>& __u)
1791 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1793 this->_M_head(*this) = __u.first;
1794 this->_M_tail(*this)._M_head(*this) = __u.second;
1798 template<typename _U1, typename _U2>
1799 requires (__assignable<_U1, _U2>())
1801 operator=(pair<_U1, _U2>&& __u)
1802 noexcept(__nothrow_assignable<_U1, _U2>())
1804 this->_M_head(*this) = std::forward<_U1>(__u.first);
1805 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1809#if __cpp_lib_ranges_zip // >= C++23
1810 template<typename _U1, typename _U2>
1811 requires (__const_assignable<const _U1&, const _U2>())
1812 constexpr const tuple&
1813 operator=(const pair<_U1, _U2>& __u) const
1815 this->_M_head(*this) = __u.first;
1816 this->_M_tail(*this)._M_head(*this) = __u.second;
1820 template<typename _U1, typename _U2>
1821 requires (__const_assignable<_U1, _U2>())
1822 constexpr const tuple&
1823 operator=(pair<_U1, _U2>&& __u) const
1825 this->_M_head(*this) = std::forward<_U1>(__u.first);
1826 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1831#if __cpp_lib_tuple_like // >= C++23
1832 template<__eligible_tuple_like<tuple> _UTuple>
1833 requires (__assignable_from_tuple_like<_UTuple>())
1835 operator=(_UTuple&& __u)
1837 this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1841 template<__eligible_tuple_like<tuple> _UTuple>
1842 requires (__const_assignable_from_tuple_like<_UTuple>())
1843 constexpr const tuple&
1844 operator=(_UTuple&& __u) const
1846 this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1850 template<__tuple_like _UTuple>
1851 requires (!__is_tuple_v<_UTuple>)
1852 friend constexpr bool
1853 operator==(const tuple& __t, const _UTuple& __u)
1855 static_assert(sizeof...(_Elements) == tuple_size_v<_UTuple>,
1856 "tuple objects can only be compared if they have equal sizes.");
1857 return [&]<size_t... _Is>(index_sequence<_Is...>) {
1858 return (bool(std::get<_Is>(__t) == std::get<_Is>(__u))
1860 }(index_sequence_for<_Elements...>{});
1863 template<__tuple_like _UTuple,
1864 typename = make_index_sequence<tuple_size_v<_UTuple>>>
1865 struct __tuple_like_common_comparison_category;
1867 template<__tuple_like _UTuple, size_t... _Is>
1869 { typename void_t<__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>; }
1870 struct __tuple_like_common_comparison_category<_UTuple, index_sequence<_Is...>>
1872 using type = common_comparison_category_t
1873 <__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>;
1876 template<__tuple_like _UTuple>
1877 requires (!__is_tuple_v<_UTuple>)
1878 friend constexpr typename __tuple_like_common_comparison_category<_UTuple>::type
1879 operator<=>(const tuple& __t, const _UTuple& __u)
1881 using _Cat = typename __tuple_like_common_comparison_category<_UTuple>::type;
1882 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Elements...>());
1886#else // ! (concepts && consteval)
1889 template<typename... _UElements>
1891 __enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
1893 { return __and_<is_assignable<_Elements&, _UElements>...>::value; }
1895 // Condition for noexcept-specifier of an assignment operator.
1896 template<typename... _UElements>
1897 static constexpr bool __nothrow_assignable()
1900 __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
1905 _GLIBCXX20_CONSTEXPR
1907 operator=(__conditional_t<__assignable<const _Elements&...>(),
1909 const __nonesuch&> __in)
1910 noexcept(__nothrow_assignable<const _Elements&...>())
1912 this->_M_assign(__in);
1916 _GLIBCXX20_CONSTEXPR
1918 operator=(__conditional_t<__assignable<_Elements...>(),
1921 noexcept(__nothrow_assignable<_Elements...>())
1923 this->_M_assign(std::move(__in));
1927 template<typename... _UElements>
1928 _GLIBCXX20_CONSTEXPR
1929 __enable_if_t<__assignable<const _UElements&...>(), tuple&>
1930 operator=(const tuple<_UElements...>& __in)
1931 noexcept(__nothrow_assignable<const _UElements&...>())
1933 this->_M_assign(__in);
1937 template<typename... _UElements>
1938 _GLIBCXX20_CONSTEXPR
1939 __enable_if_t<__assignable<_UElements...>(), tuple&>
1940 operator=(tuple<_UElements...>&& __in)
1941 noexcept(__nothrow_assignable<_UElements...>())
1943 this->_M_assign(std::move(__in));
1946#endif // concepts && consteval
1949 _GLIBCXX20_CONSTEXPR
1952 noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
1953 { _Inherited::_M_swap(__in); }
1955#if __cpp_lib_ranges_zip // >= C++23
1956 // As an extension, we constrain the const swap member function in order
1957 // to continue accepting explicit instantiation of tuples whose elements
1958 // are not all const swappable. Without this constraint, such an
1959 // explicit instantiation would also instantiate the ill-formed body of
1960 // this function and yield a hard error. This constraint shouldn't
1961 // affect the behavior of valid programs.
1963 swap(const tuple& __in) const
1964 noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
1965 requires (is_swappable_v<const _Elements> && ...)
1966 { _Inherited::_M_swap(__in); }
1970#if __cpp_deduction_guides >= 201606
1971 template<typename... _UTypes>
1972 tuple(_UTypes...) -> tuple<_UTypes...>;
1973 template<typename _T1, typename _T2>
1974 tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
1975 template<typename _Alloc, typename... _UTypes>
1976 tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
1977 template<typename _Alloc, typename _T1, typename _T2>
1978 tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
1979 template<typename _Alloc, typename... _UTypes>
1980 tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
1983 // Explicit specialization, zero-element tuple.
1988 _GLIBCXX20_CONSTEXPR
1989 void swap(tuple&) noexcept { /* no-op */ }
1990#if __cpp_lib_ranges_zip // >= C++23
1991 constexpr void swap(const tuple&) const noexcept { /* no-op */ }
1993 // We need the default since we're going to define no-op
1994 // allocator constructors.
1996 // No-op allocator constructors.
1997 template<typename _Alloc>
1998 _GLIBCXX20_CONSTEXPR
1999 tuple(allocator_arg_t, const _Alloc&) noexcept { }
2000 template<typename _Alloc>
2001 _GLIBCXX20_CONSTEXPR
2002 tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
2005#if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20
2006 /// Partial specialization, 2-element tuple.
2007 /// Includes construction and assignment from a pair.
2008 template<typename _T1, typename _T2>
2009 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
2011 typedef _Tuple_impl<0, _T1, _T2> _Inherited;
2013 // Constraint for non-explicit default constructor
2014 template<bool _Dummy, typename _U1, typename _U2>
2015 using _ImplicitDefaultCtor = __enable_if_t<
2016 _TupleConstraints<_Dummy, _U1, _U2>::
2017 __is_implicitly_default_constructible(),
2020 // Constraint for explicit default constructor
2021 template<bool _Dummy, typename _U1, typename _U2>
2022 using _ExplicitDefaultCtor = __enable_if_t<
2023 _TupleConstraints<_Dummy, _U1, _U2>::
2024 __is_explicitly_default_constructible(),
2027 template<bool _Dummy>
2028 using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
2030 // Constraint for non-explicit constructors
2031 template<bool _Cond, typename _U1, typename _U2>
2032 using _ImplicitCtor = __enable_if_t<
2033 _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
2036 // Constraint for non-explicit constructors
2037 template<bool _Cond, typename _U1, typename _U2>
2038 using _ExplicitCtor = __enable_if_t<
2039 _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
2042 template<typename _U1, typename _U2>
2043 static constexpr bool __assignable()
2045 return __and_<is_assignable<_T1&, _U1>,
2046 is_assignable<_T2&, _U2>>::value;
2049 template<typename _U1, typename _U2>
2050 static constexpr bool __nothrow_assignable()
2052 return __and_<is_nothrow_assignable<_T1&, _U1>,
2053 is_nothrow_assignable<_T2&, _U2>>::value;
2056 template<typename _U1, typename _U2>
2057 static constexpr bool __nothrow_constructible()
2059 return __and_<is_nothrow_constructible<_T1, _U1>,
2060 is_nothrow_constructible<_T2, _U2>>::value;
2063 static constexpr bool __nothrow_default_constructible()
2065 return __and_<is_nothrow_default_constructible<_T1>,
2066 is_nothrow_default_constructible<_T2>>::value;
2069 template<typename _U1>
2070 static constexpr bool __is_alloc_arg()
2071 { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
2073 /// @cond undocumented
2074#undef __glibcxx_no_dangling_refs
2075 // Error if construction from _U1 and _U2 would create a dangling ref.
2076#if __has_builtin(__reference_constructs_from_temporary) \
2077 && defined _GLIBCXX_DEBUG
2078# define __glibcxx_no_dangling_refs(_U1, _U2) \
2079 static_assert(!__reference_constructs_from_temporary(_T1, _U1) \
2080 && !__reference_constructs_from_temporary(_T2, _U2), \
2081 "std::tuple constructor creates a dangling reference")
2083# define __glibcxx_no_dangling_refs(_U1, _U2)
2088 template<bool _Dummy = true,
2089 _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
2092 noexcept(__nothrow_default_constructible())
2095 template<bool _Dummy = true,
2096 _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
2099 noexcept(__nothrow_default_constructible())
2102 template<bool _Dummy = true,
2103 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2105 tuple(const _T1& __a1, const _T2& __a2)
2106 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2107 : _Inherited(__a1, __a2) { }
2109 template<bool _Dummy = true,
2110 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2112 tuple(const _T1& __a1, const _T2& __a2)
2113 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2114 : _Inherited(__a1, __a2) { }
2116 template<typename _U1, typename _U2,
2117 _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
2119 tuple(_U1&& __a1, _U2&& __a2)
2120 noexcept(__nothrow_constructible<_U1, _U2>())
2121 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2122 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2124 template<typename _U1, typename _U2,
2125 _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
2127 tuple(_U1&& __a1, _U2&& __a2)
2128 noexcept(__nothrow_constructible<_U1, _U2>())
2129 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2130 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2132 constexpr tuple(const tuple&) = default;
2134 constexpr tuple(tuple&&) = default;
2136 template<typename _U1, typename _U2,
2137 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2139 tuple(const tuple<_U1, _U2>& __in)
2140 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2141 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2142 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2144 template<typename _U1, typename _U2,
2145 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2147 tuple(const tuple<_U1, _U2>& __in)
2148 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2149 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2150 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2152 template<typename _U1, typename _U2,
2153 _ImplicitCtor<true, _U1, _U2> = true>
2155 tuple(tuple<_U1, _U2>&& __in)
2156 noexcept(__nothrow_constructible<_U1, _U2>())
2157 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2158 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2160 template<typename _U1, typename _U2,
2161 _ExplicitCtor<true, _U1, _U2> = false>
2163 tuple(tuple<_U1, _U2>&& __in)
2164 noexcept(__nothrow_constructible<_U1, _U2>())
2165 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2166 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2168 template<typename _U1, typename _U2,
2169 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2171 tuple(const pair<_U1, _U2>& __in)
2172 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2173 : _Inherited(__in.first, __in.second)
2174 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2176 template<typename _U1, typename _U2,
2177 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2179 tuple(const pair<_U1, _U2>& __in)
2180 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2181 : _Inherited(__in.first, __in.second)
2182 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2184 template<typename _U1, typename _U2,
2185 _ImplicitCtor<true, _U1, _U2> = true>
2187 tuple(pair<_U1, _U2>&& __in)
2188 noexcept(__nothrow_constructible<_U1, _U2>())
2189 : _Inherited(std::forward<_U1>(__in.first),
2190 std::forward<_U2>(__in.second))
2191 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2193 template<typename _U1, typename _U2,
2194 _ExplicitCtor<true, _U1, _U2> = false>
2196 tuple(pair<_U1, _U2>&& __in)
2197 noexcept(__nothrow_constructible<_U1, _U2>())
2198 : _Inherited(std::forward<_U1>(__in.first),
2199 std::forward<_U2>(__in.second))
2200 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2202 // Allocator-extended constructors.
2204 template<typename _Alloc,
2205 _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
2206 _GLIBCXX20_CONSTEXPR
2207 tuple(allocator_arg_t __tag, const _Alloc& __a)
2208 : _Inherited(__tag, __a) { }
2210 template<typename _Alloc,
2211 _ExplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = false>
2212 _GLIBCXX20_CONSTEXPR
2214 tuple(allocator_arg_t __tag, const _Alloc& __a)
2215 : _Inherited(__tag, __a) { }
2217 template<typename _Alloc, bool _Dummy = true,
2218 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2219 _GLIBCXX20_CONSTEXPR
2220 tuple(allocator_arg_t __tag, const _Alloc& __a,
2221 const _T1& __a1, const _T2& __a2)
2222 : _Inherited(__tag, __a, __a1, __a2) { }
2224 template<typename _Alloc, bool _Dummy = true,
2225 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2227 _GLIBCXX20_CONSTEXPR
2228 tuple(allocator_arg_t __tag, const _Alloc& __a,
2229 const _T1& __a1, const _T2& __a2)
2230 : _Inherited(__tag, __a, __a1, __a2) { }
2232 template<typename _Alloc, typename _U1, typename _U2,
2233 _ImplicitCtor<true, _U1, _U2> = true>
2234 _GLIBCXX20_CONSTEXPR
2235 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
2236 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2237 std::forward<_U2>(__a2))
2238 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2240 template<typename _Alloc, typename _U1, typename _U2,
2241 _ExplicitCtor<true, _U1, _U2> = false>
2243 _GLIBCXX20_CONSTEXPR
2244 tuple(allocator_arg_t __tag, const _Alloc& __a,
2245 _U1&& __a1, _U2&& __a2)
2246 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2247 std::forward<_U2>(__a2))
2248 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2250 template<typename _Alloc>
2251 _GLIBCXX20_CONSTEXPR
2252 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
2253 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
2255 template<typename _Alloc>
2256 _GLIBCXX20_CONSTEXPR
2257 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
2258 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
2260 template<typename _Alloc, typename _U1, typename _U2,
2261 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2262 _GLIBCXX20_CONSTEXPR
2263 tuple(allocator_arg_t __tag, const _Alloc& __a,
2264 const tuple<_U1, _U2>& __in)
2265 : _Inherited(__tag, __a,
2266 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2267 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2269 template<typename _Alloc, typename _U1, typename _U2,
2270 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2272 _GLIBCXX20_CONSTEXPR
2273 tuple(allocator_arg_t __tag, const _Alloc& __a,
2274 const tuple<_U1, _U2>& __in)
2275 : _Inherited(__tag, __a,
2276 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2277 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2279 template<typename _Alloc, typename _U1, typename _U2,
2280 _ImplicitCtor<true, _U1, _U2> = true>
2281 _GLIBCXX20_CONSTEXPR
2282 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2283 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2284 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2286 template<typename _Alloc, typename _U1, typename _U2,
2287 _ExplicitCtor<true, _U1, _U2> = false>
2289 _GLIBCXX20_CONSTEXPR
2290 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2291 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2292 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2294 template<typename _Alloc, typename _U1, typename _U2,
2295 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2296 _GLIBCXX20_CONSTEXPR
2297 tuple(allocator_arg_t __tag, const _Alloc& __a,
2298 const pair<_U1, _U2>& __in)
2299 : _Inherited(__tag, __a, __in.first, __in.second)
2300 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2302 template<typename _Alloc, typename _U1, typename _U2,
2303 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2305 _GLIBCXX20_CONSTEXPR
2306 tuple(allocator_arg_t __tag, const _Alloc& __a,
2307 const pair<_U1, _U2>& __in)
2308 : _Inherited(__tag, __a, __in.first, __in.second)
2309 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2311 template<typename _Alloc, typename _U1, typename _U2,
2312 _ImplicitCtor<true, _U1, _U2> = true>
2313 _GLIBCXX20_CONSTEXPR
2314 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2315 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2316 std::forward<_U2>(__in.second))
2317 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2319 template<typename _Alloc, typename _U1, typename _U2,
2320 _ExplicitCtor<true, _U1, _U2> = false>
2322 _GLIBCXX20_CONSTEXPR
2323 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2324 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2325 std::forward<_U2>(__in.second))
2326 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2328 // Tuple assignment.
2330 _GLIBCXX20_CONSTEXPR
2332 operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
2334 const __nonesuch&> __in)
2335 noexcept(__nothrow_assignable<const _T1&, const _T2&>())
2337 this->_M_assign(__in);
2341 _GLIBCXX20_CONSTEXPR
2343 operator=(__conditional_t<__assignable<_T1, _T2>(),
2346 noexcept(__nothrow_assignable<_T1, _T2>())
2348 this->_M_assign(std::move(__in));
2352 template<typename _U1, typename _U2>
2353 _GLIBCXX20_CONSTEXPR
2354 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2355 operator=(const tuple<_U1, _U2>& __in)
2356 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2358 this->_M_assign(__in);
2362 template<typename _U1, typename _U2>
2363 _GLIBCXX20_CONSTEXPR
2364 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2365 operator=(tuple<_U1, _U2>&& __in)
2366 noexcept(__nothrow_assignable<_U1, _U2>())
2368 this->_M_assign(std::move(__in));
2372 template<typename _U1, typename _U2>
2373 _GLIBCXX20_CONSTEXPR
2374 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2375 operator=(const pair<_U1, _U2>& __in)
2376 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2378 this->_M_head(*this) = __in.first;
2379 this->_M_tail(*this)._M_head(*this) = __in.second;
2383 template<typename _U1, typename _U2>
2384 _GLIBCXX20_CONSTEXPR
2385 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2386 operator=(pair<_U1, _U2>&& __in)
2387 noexcept(__nothrow_assignable<_U1, _U2>())
2389 this->_M_head(*this) = std::forward<_U1>(__in.first);
2390 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
2394 _GLIBCXX20_CONSTEXPR
2397 noexcept(__and_<__is_nothrow_swappable<_T1>,
2398 __is_nothrow_swappable<_T2>>::value)
2399 { _Inherited::_M_swap(__in); }
2401#endif // concepts && conditional_explicit
2403 /// class tuple_size
2404 template<typename... _Elements>
2405 struct tuple_size<tuple<_Elements...>>
2406 : public integral_constant<size_t, sizeof...(_Elements)> { };
2408#if __cplusplus >= 201703L
2409 template<typename... _Types>
2410 inline constexpr size_t tuple_size_v<tuple<_Types...>>
2411 = sizeof...(_Types);
2413 template<typename... _Types>
2414 inline constexpr size_t tuple_size_v<const tuple<_Types...>>
2415 = sizeof...(_Types);
2418 /// Trait to get the Ith element type from a tuple.
2419 template<size_t __i, typename... _Types>
2420 struct tuple_element<__i, tuple<_Types...>>
2422 static_assert(__i < sizeof...(_Types), "tuple index must be in range");
2424 using type = typename _Nth_type<__i, _Types...>::type;
2427 template<size_t __i, typename _Head, typename... _Tail>
2429 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2430 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2432 template<size_t __i, typename _Head, typename... _Tail>
2433 constexpr const _Head&
2434 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2435 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2437 // Deleted overload to improve diagnostics for invalid indices
2438 template<size_t __i, typename... _Types>
2439 __enable_if_t<(__i >= sizeof...(_Types))>
2440 __get_helper(const tuple<_Types...>&) = delete;
2442 /// Return a reference to the ith element of a tuple.
2443 template<size_t __i, typename... _Elements>
2444 constexpr __tuple_element_t<__i, tuple<_Elements...>>&
2445 get(tuple<_Elements...>& __t) noexcept
2446 { return std::__get_helper<__i>(__t); }
2448 /// Return a const reference to the ith element of a const tuple.
2449 template<size_t __i, typename... _Elements>
2450 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
2451 get(const tuple<_Elements...>& __t) noexcept
2452 { return std::__get_helper<__i>(__t); }
2454 /// Return an rvalue reference to the ith element of a tuple rvalue.
2455 template<size_t __i, typename... _Elements>
2456 constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
2457 get(tuple<_Elements...>&& __t) noexcept
2459 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2460 return std::forward<__element_type>(std::__get_helper<__i>(__t));
2463 /// Return a const rvalue reference to the ith element of a const tuple rvalue.
2464 template<size_t __i, typename... _Elements>
2465 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
2466 get(const tuple<_Elements...>&& __t) noexcept
2468 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2469 return std::forward<const __element_type>(std::__get_helper<__i>(__t));
2472 /// @cond undocumented
2473 // Deleted overload chosen for invalid indices.
2474 template<size_t __i, typename... _Elements>
2475 constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
2476 get(const tuple<_Elements...>&) = delete;
2479#ifdef __cpp_lib_tuples_by_type // C++ >= 14
2480 /// Return a reference to the unique element of type _Tp of a tuple.
2481 template <typename _Tp, typename... _Types>
2483 get(tuple<_Types...>& __t) noexcept
2485 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2486 static_assert(__idx < sizeof...(_Types),
2487 "the type T in std::get<T> must occur exactly once in the tuple");
2488 return std::__get_helper<__idx>(__t);
2491 /// Return a reference to the unique element of type _Tp of a tuple rvalue.
2492 template <typename _Tp, typename... _Types>
2494 get(tuple<_Types...>&& __t) noexcept
2496 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2497 static_assert(__idx < sizeof...(_Types),
2498 "the type T in std::get<T> must occur exactly once in the tuple");
2499 return std::forward<_Tp>(std::__get_helper<__idx>(__t));
2502 /// Return a const reference to the unique element of type _Tp of a tuple.
2503 template <typename _Tp, typename... _Types>
2504 constexpr const _Tp&
2505 get(const tuple<_Types...>& __t) noexcept
2507 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2508 static_assert(__idx < sizeof...(_Types),
2509 "the type T in std::get<T> must occur exactly once in the tuple");
2510 return std::__get_helper<__idx>(__t);
2513 /// Return a const reference to the unique element of type _Tp of
2514 /// a const tuple rvalue.
2515 template <typename _Tp, typename... _Types>
2516 constexpr const _Tp&&
2517 get(const tuple<_Types...>&& __t) noexcept
2519 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2520 static_assert(__idx < sizeof...(_Types),
2521 "the type T in std::get<T> must occur exactly once in the tuple");
2522 return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
2526 // This class performs the comparison operations on tuples
2527 template<typename _Tp, typename _Up, size_t __i, size_t __size>
2528 struct __tuple_compare
2530 static constexpr bool
2531 __eq(const _Tp& __t, const _Up& __u)
2533 return bool(std::get<__i>(__t) == std::get<__i>(__u))
2534 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
2537 static constexpr bool
2538 __less(const _Tp& __t, const _Up& __u)
2540 return bool(std::get<__i>(__t) < std::get<__i>(__u))
2541 || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
2542 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
2546 template<typename _Tp, typename _Up, size_t __size>
2547 struct __tuple_compare<_Tp, _Up, __size, __size>
2549 static constexpr bool
2550 __eq(const _Tp&, const _Up&) { return true; }
2552 static constexpr bool
2553 __less(const _Tp&, const _Up&) { return false; }
2556 template<typename... _TElements, typename... _UElements>
2558 operator==(const tuple<_TElements...>& __t,
2559 const tuple<_UElements...>& __u)
2561 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2562 "tuple objects can only be compared if they have equal sizes.");
2563 using __compare = __tuple_compare<tuple<_TElements...>,
2564 tuple<_UElements...>,
2565 0, sizeof...(_TElements)>;
2566 return __compare::__eq(__t, __u);
2569#if __cpp_lib_three_way_comparison
2570 template<typename _Cat, typename _Tp, typename _Up>
2572 __tuple_cmp(const _Tp&, const _Up&, index_sequence<>)
2573 { return _Cat::equivalent; }
2575 template<typename _Cat, typename _Tp, typename _Up,
2576 size_t _Idx0, size_t... _Idxs>
2578 __tuple_cmp(const _Tp& __t, const _Up& __u,
2579 index_sequence<_Idx0, _Idxs...>)
2582 = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u));
2585 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>());
2588 template<typename... _Tps, typename... _Ups>
2590 common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
2591 operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
2594 = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
2595 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
2598 template<typename... _TElements, typename... _UElements>
2600 operator<(const tuple<_TElements...>& __t,
2601 const tuple<_UElements...>& __u)
2603 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2604 "tuple objects can only be compared if they have equal sizes.");
2605 using __compare = __tuple_compare<tuple<_TElements...>,
2606 tuple<_UElements...>,
2607 0, sizeof...(_TElements)>;
2608 return __compare::__less(__t, __u);
2611 template<typename... _TElements, typename... _UElements>
2613 operator!=(const tuple<_TElements...>& __t,
2614 const tuple<_UElements...>& __u)
2615 { return !(__t == __u); }
2617 template<typename... _TElements, typename... _UElements>
2619 operator>(const tuple<_TElements...>& __t,
2620 const tuple<_UElements...>& __u)
2621 { return __u < __t; }
2623 template<typename... _TElements, typename... _UElements>
2625 operator<=(const tuple<_TElements...>& __t,
2626 const tuple<_UElements...>& __u)
2627 { return !(__u < __t); }
2629 template<typename... _TElements, typename... _UElements>
2631 operator>=(const tuple<_TElements...>& __t,
2632 const tuple<_UElements...>& __u)
2633 { return !(__t < __u); }
2634#endif // three_way_comparison
2637 /// Create a tuple containing copies of the arguments
2638 template<typename... _Elements>
2639 constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
2640 make_tuple(_Elements&&... __args)
2642 typedef tuple<typename __decay_and_strip<_Elements>::__type...>
2644 return __result_type(std::forward<_Elements>(__args)...);
2647 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2648 // 2275. Why is forward_as_tuple not constexpr?
2649 /// Create a tuple of lvalue or rvalue references to the arguments
2650 template<typename... _Elements>
2651 constexpr tuple<_Elements&&...>
2652 forward_as_tuple(_Elements&&... __args) noexcept
2653 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2655 /// @cond undocumented
2656 template<size_t, typename, typename, size_t>
2657 struct __make_tuple_impl;
2659 template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
2660 struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
2661 : __make_tuple_impl<_Idx + 1,
2662 tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
2666 template<size_t _Nm, typename _Tuple, typename... _Tp>
2667 struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
2669 typedef tuple<_Tp...> __type;
2672 template<typename _Tuple>
2673 struct __do_make_tuple
2674 : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
2677 // Returns the std::tuple equivalent of a tuple-like type.
2678 template<typename _Tuple>
2680 : public __do_make_tuple<__remove_cvref_t<_Tuple>>
2683 // Combines several std::tuple's into a single one.
2684 template<typename...>
2685 struct __combine_tuples;
2688 struct __combine_tuples<>
2690 typedef tuple<> __type;
2693 template<typename... _Ts>
2694 struct __combine_tuples<tuple<_Ts...>>
2696 typedef tuple<_Ts...> __type;
2699 template<typename... _T1s, typename... _T2s, typename... _Rem>
2700 struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
2702 typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
2703 _Rem...>::__type __type;
2706 // Computes the result type of tuple_cat given a set of tuple-like types.
2707 template<typename... _Tpls>
2708 struct __tuple_cat_result
2710 typedef typename __combine_tuples
2711 <typename __make_tuple<_Tpls>::__type...>::__type __type;
2714 // Helper to determine the index set for the first tuple-like
2715 // type of a given set.
2716 template<typename...>
2717 struct __make_1st_indices;
2720 struct __make_1st_indices<>
2722 typedef _Index_tuple<> __type;
2725 template<typename _Tp, typename... _Tpls>
2726 struct __make_1st_indices<_Tp, _Tpls...>
2728 typedef typename _Build_index_tuple<tuple_size<
2729 typename remove_reference<_Tp>::type>::value>::__type __type;
2732 // Performs the actual concatenation by step-wise expanding tuple-like
2733 // objects into the elements, which are finally forwarded into the
2735 template<typename _Ret, typename _Indices, typename... _Tpls>
2736 struct __tuple_concater;
2738 template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2739 struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2741 template<typename... _Us>
2742 static constexpr _Ret
2743 _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2745 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2746 typedef __tuple_concater<_Ret, __idx, _Tpls...> __next;
2747 return __next::_S_do(std::forward<_Tpls>(__tps)...,
2748 std::forward<_Us>(__us)...,
2749 std::get<_Is>(std::forward<_Tp>(__tp))...);
2753 template<typename _Ret>
2754 struct __tuple_concater<_Ret, _Index_tuple<>>
2756 template<typename... _Us>
2757 static constexpr _Ret
2758 _S_do(_Us&&... __us)
2760 return _Ret(std::forward<_Us>(__us)...);
2764 template<typename... _Tps>
2765 struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2769 /// Create a `tuple` containing all elements from multiple tuple-like objects
2770#if __cpp_lib_tuple_like // >= C++23
2771 template<__tuple_like... _Tpls>
2773 template<typename... _Tpls, typename = typename
2774 enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2777 tuple_cat(_Tpls&&... __tpls)
2778 -> typename __tuple_cat_result<_Tpls...>::__type
2780 typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2781 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2782 typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2783 return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2786 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2787 // 2301. Why is tie not constexpr?
2788 /// Return a tuple of lvalue references bound to the arguments
2789 template<typename... _Elements>
2790 constexpr tuple<_Elements&...>
2791 tie(_Elements&... __args) noexcept
2792 { return tuple<_Elements&...>(__args...); }
2794 /// Exchange the values of two tuples
2795 template<typename... _Elements>
2796 _GLIBCXX20_CONSTEXPR
2798#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2799 // Constrained free swap overload, see p0185r1
2800 typename enable_if<__and_<__is_swappable<_Elements>...>::value
2805 swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
2806 noexcept(noexcept(__x.swap(__y)))
2809#if __cpp_lib_ranges_zip // >= C++23
2810 template<typename... _Elements>
2811 requires (is_swappable_v<const _Elements> && ...)
2813 swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2814 noexcept(noexcept(__x.swap(__y)))
2818#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2819 /// Exchange the values of two const tuples (if const elements can be swapped)
2820 template<typename... _Elements>
2821 _GLIBCXX20_CONSTEXPR
2822 typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2823 swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2826 // A class (and instance) which can be used in 'tie' when an element
2827 // of a tuple is not required.
2828 // _GLIBCXX14_CONSTEXPR
2829 // 2933. PR for LWG 2773 could be clearer
2830 struct _Swallow_assign
2833 _GLIBCXX14_CONSTEXPR const _Swallow_assign&
2834 operator=(const _Tp&) const
2838 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2839 // 2773. Making std::ignore constexpr
2840 /** Used with `std::tie` to ignore an element of a tuple
2842 * When using `std::tie` to assign the elements of a tuple to variables,
2843 * unwanted elements can be ignored by using `std::ignore`. For example:
2847 * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3);
2850 * This assignment will perform `x=1; std::ignore=2; y=3;` which results
2851 * in the second element being ignored.
2855 _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{};
2857 /// Partial specialization for tuples
2858 template<typename... _Types, typename _Alloc>
2859 struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2861 // See stl_pair.h...
2862 /** "piecewise construction" using a tuple of arguments for each member.
2864 * @param __first Arguments for the first member of the pair.
2865 * @param __second Arguments for the second member of the pair.
2867 * The elements of each tuple will be used as the constructor arguments
2868 * for the data members of the pair.
2870 template<class _T1, class _T2>
2871 template<typename... _Args1, typename... _Args2>
2872 _GLIBCXX20_CONSTEXPR
2875 pair(piecewise_construct_t,
2876 tuple<_Args1...> __first, tuple<_Args2...> __second)
2877 : pair(__first, __second,
2878 typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2879 typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2882 template<class _T1, class _T2>
2883 template<typename... _Args1, size_t... _Indexes1,
2884 typename... _Args2, size_t... _Indexes2>
2885 _GLIBCXX20_CONSTEXPR inline
2887 pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2888 _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2889 : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2890 second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2893#if defined(__cpp_lib_apply) || defined(__cpp_lib_make_from_tuple) // C++ >= 17
2894 // Unpack a std::tuple into a type trait and use its value.
2895 // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2896 // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2897 // Otherwise the result is false (because we don't know if std::get throws).
2898 template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2899 inline constexpr bool __unpack_std_tuple = false;
2901 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2902 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2903 = _Trait<_Tp, _Up...>::value;
2905 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2906 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2907 = _Trait<_Tp, _Up&...>::value;
2909 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2910 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2911 = _Trait<_Tp, const _Up...>::value;
2913 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2914 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2915 = _Trait<_Tp, const _Up&...>::value;
2918#ifdef __cpp_lib_apply // C++ >= 17
2919 template <typename _Fn, typename _Tuple, size_t... _Idx>
2920 constexpr decltype(auto)
2921 __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2923 return std::__invoke(std::forward<_Fn>(__f),
2924 std::get<_Idx>(std::forward<_Tuple>(__t))...);
2927#if __cpp_lib_tuple_like // >= C++23
2928 template <typename _Fn, __tuple_like _Tuple>
2930 template <typename _Fn, typename _Tuple>
2932 constexpr decltype(auto)
2933 apply(_Fn&& __f, _Tuple&& __t)
2934 noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2937 = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2938 return std::__apply_impl(std::forward<_Fn>(__f),
2939 std::forward<_Tuple>(__t),
2944#ifdef __cpp_lib_make_from_tuple // C++ >= 17
2945 template <typename _Tp, typename _Tuple, size_t... _Idx>
2947 __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
2948 { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
2950#if __cpp_lib_tuple_like // >= C++23
2951 template <typename _Tp, __tuple_like _Tuple>
2953 template <typename _Tp, typename _Tuple>
2956 make_from_tuple(_Tuple&& __t)
2957 noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
2959 constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
2960#if __has_builtin(__reference_constructs_from_temporary)
2961 if constexpr (__n == 1)
2963 using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
2964 static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
2967 return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
2968 make_index_sequence<__n>{});
2972#if __cpp_lib_tuple_like // >= C++23
2973 template<__tuple_like _TTuple, __tuple_like _UTuple,
2974 template<typename> class _TQual, template<typename> class _UQual,
2975 typename = make_index_sequence<tuple_size_v<_TTuple>>>
2976 struct __tuple_like_common_reference;
2978 template<__tuple_like _TTuple, __tuple_like _UTuple,
2979 template<typename> class _TQual, template<typename> class _UQual,
2982 { typename tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2983 _UQual<tuple_element_t<_Is, _UTuple>>>...>; }
2984 struct __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual, index_sequence<_Is...>>
2986 using type = tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2987 _UQual<tuple_element_t<_Is, _UTuple>>>...>;
2990 template<__tuple_like _TTuple, __tuple_like _UTuple,
2991 template<typename> class _TQual, template<typename> class _UQual>
2992 requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
2993 && is_same_v<_TTuple, decay_t<_TTuple>>
2994 && is_same_v<_UTuple, decay_t<_UTuple>>
2995 && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
2996 && requires { typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type; }
2997 struct basic_common_reference<_TTuple, _UTuple, _TQual, _UQual>
2999 using type = typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type;
3002 template<__tuple_like _TTuple, __tuple_like _UTuple,
3003 typename = make_index_sequence<tuple_size_v<_TTuple>>>
3004 struct __tuple_like_common_type;
3006 template<__tuple_like _TTuple, __tuple_like _UTuple, size_t... _Is>
3008 { typename tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3009 tuple_element_t<_Is, _UTuple>>...>; }
3010 struct __tuple_like_common_type<_TTuple, _UTuple, index_sequence<_Is...>>
3012 using type = tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3013 tuple_element_t<_Is, _UTuple>>...>;
3016 template<__tuple_like _TTuple, __tuple_like _UTuple>
3017 requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
3018 && is_same_v<_TTuple, decay_t<_TTuple>>
3019 && is_same_v<_UTuple, decay_t<_UTuple>>
3020 && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
3021 && requires { typename __tuple_like_common_type<_TTuple, _UTuple>::type; }
3022 struct common_type<_TTuple, _UTuple>
3024 using type = typename __tuple_like_common_type<_TTuple, _UTuple>::type;
3030#undef __glibcxx_no_dangling_refs
3032_GLIBCXX_END_NAMESPACE_VERSION
3037#endif // _GLIBCXX_TUPLE