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 // Defined as a template to work around PR libstdc++/116440.
973 template<typename = void>
974 constexpr explicit(!__convertible<const _Elements&...>())
975 tuple(const _Elements&... __elements)
976 noexcept(__nothrow_constructible<const _Elements&...>())
977 requires (__constructible<const _Elements&...>())
978 : _Inherited(__elements...)
981 template<typename... _UTypes>
982 requires (__disambiguating_constraint<_UTypes...>())
983 && (__constructible<_UTypes...>())
984 && (!__dangles<_UTypes...>())
985 constexpr explicit(!__convertible<_UTypes...>())
986 tuple(_UTypes&&... __u)
987 noexcept(__nothrow_constructible<_UTypes...>())
988 : _Inherited(std::forward<_UTypes>(__u)...)
991 template<typename... _UTypes>
992 requires (__disambiguating_constraint<_UTypes...>())
993 && (__constructible<_UTypes...>())
994 && (__dangles<_UTypes...>())
995 tuple(_UTypes&&...) = delete;
997 constexpr tuple(const tuple&) = default;
999 constexpr tuple(tuple&&) = default;
1001 template<typename... _UTypes>
1002 requires (__constructible<const _UTypes&...>())
1003 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1004 && (!__dangles<const _UTypes&...>())
1005 constexpr explicit(!__convertible<const _UTypes&...>())
1006 tuple(const tuple<_UTypes...>& __u)
1007 noexcept(__nothrow_constructible<const _UTypes&...>())
1008 : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1011 template<typename... _UTypes>
1012 requires (__constructible<const _UTypes&...>())
1013 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1014 && (__dangles<const _UTypes&...>())
1015 tuple(const tuple<_UTypes...>&) = delete;
1017 template<typename... _UTypes>
1018 requires (__constructible<_UTypes...>())
1019 && (!__use_other_ctor<tuple<_UTypes...>>())
1020 && (!__dangles<_UTypes...>())
1021 constexpr explicit(!__convertible<_UTypes...>())
1022 tuple(tuple<_UTypes...>&& __u)
1023 noexcept(__nothrow_constructible<_UTypes...>())
1024 : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1027 template<typename... _UTypes>
1028 requires (__constructible<_UTypes...>())
1029 && (!__use_other_ctor<tuple<_UTypes...>>())
1030 && (__dangles<_UTypes...>())
1031 tuple(tuple<_UTypes...>&&) = delete;
1033#if __cpp_lib_ranges_zip // >= C++23
1034 template<typename... _UTypes>
1035 requires (__constructible<_UTypes&...>())
1036 && (!__use_other_ctor<tuple<_UTypes...>&>())
1037 && (!__dangles<_UTypes&...>())
1038 constexpr explicit(!__convertible<_UTypes&...>())
1039 tuple(tuple<_UTypes...>& __u)
1040 noexcept(__nothrow_constructible<_UTypes&...>())
1041 : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1044 template<typename... _UTypes>
1045 requires (__constructible<_UTypes&...>())
1046 && (!__use_other_ctor<tuple<_UTypes...>&>())
1047 && (__dangles<_UTypes&...>())
1048 tuple(tuple<_UTypes...>&) = delete;
1050 template<typename... _UTypes>
1051 requires (__constructible<const _UTypes...>())
1052 && (!__use_other_ctor<const tuple<_UTypes...>>())
1053 && (!__dangles<const _UTypes...>())
1054 constexpr explicit(!__convertible<const _UTypes...>())
1055 tuple(const tuple<_UTypes...>&& __u)
1056 noexcept(__nothrow_constructible<const _UTypes...>())
1057 : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1060 template<typename... _UTypes>
1061 requires (__constructible<const _UTypes...>())
1062 && (!__use_other_ctor<const tuple<_UTypes...>>())
1063 && (__dangles<const _UTypes...>())
1064 tuple(const tuple<_UTypes...>&&) = delete;
1067 template<typename _U1, typename _U2>
1068 requires (sizeof...(_Elements) == 2)
1069 && (__constructible<const _U1&, const _U2&>())
1070 && (!__dangles<const _U1&, const _U2&>())
1071 constexpr explicit(!__convertible<const _U1&, const _U2&>())
1072 tuple(const pair<_U1, _U2>& __u)
1073 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1074 : _Inherited(__u.first, __u.second)
1077 template<typename _U1, typename _U2>
1078 requires (sizeof...(_Elements) == 2)
1079 && (__constructible<const _U1&, const _U2&>())
1080 && (__dangles<const _U1&, const _U2&>())
1081 tuple(const pair<_U1, _U2>&) = delete;
1083 template<typename _U1, typename _U2>
1084 requires (sizeof...(_Elements) == 2)
1085 && (__constructible<_U1, _U2>())
1086 && (!__dangles<_U1, _U2>())
1087 constexpr explicit(!__convertible<_U1, _U2>())
1088 tuple(pair<_U1, _U2>&& __u)
1089 noexcept(__nothrow_constructible<_U1, _U2>())
1090 : _Inherited(std::forward<_U1>(__u.first),
1091 std::forward<_U2>(__u.second))
1094 template<typename _U1, typename _U2>
1095 requires (sizeof...(_Elements) == 2)
1096 && (__constructible<_U1, _U2>())
1097 && (__dangles<_U1, _U2>())
1098 tuple(pair<_U1, _U2>&&) = delete;
1100#if __cpp_lib_ranges_zip // >= C++23
1101 template<typename _U1, typename _U2>
1102 requires (sizeof...(_Elements) == 2)
1103 && (__constructible<_U1&, _U2&>())
1104 && (!__dangles<_U1&, _U2&>())
1105 constexpr explicit(!__convertible<_U1&, _U2&>())
1106 tuple(pair<_U1, _U2>& __u)
1107 noexcept(__nothrow_constructible<_U1&, _U2&>())
1108 : _Inherited(__u.first, __u.second)
1111 template<typename _U1, typename _U2>
1112 requires (sizeof...(_Elements) == 2)
1113 && (__constructible<_U1&, _U2&>())
1114 && (__dangles<_U1&, _U2&>())
1115 tuple(pair<_U1, _U2>&) = delete;
1117 template<typename _U1, typename _U2>
1118 requires (sizeof...(_Elements) == 2)
1119 && (__constructible<const _U1, const _U2>())
1120 && (!__dangles<const _U1, const _U2>())
1121 constexpr explicit(!__convertible<const _U1, const _U2>())
1122 tuple(const pair<_U1, _U2>&& __u)
1123 noexcept(__nothrow_constructible<const _U1, const _U2>())
1124 : _Inherited(std::forward<const _U1>(__u.first),
1125 std::forward<const _U2>(__u.second))
1128 template<typename _U1, typename _U2>
1129 requires (sizeof...(_Elements) == 2)
1130 && (__constructible<const _U1, const _U2>())
1131 && (__dangles<const _U1, const _U2>())
1132 tuple(const pair<_U1, _U2>&&) = delete;
1135#if __cpp_lib_tuple_like // >= C++23
1136 template<__eligible_tuple_like<tuple> _UTuple>
1137 requires (__constructible_from_tuple_like<_UTuple>())
1138 && (!__use_other_ctor<_UTuple>())
1139 && (!__dangles_from_tuple_like<_UTuple>())
1140 constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
1141 tuple(_UTuple&& __u)
1142 : _Inherited(__tuple_like_tag_t{},
1143 std::forward<_UTuple>(__u),
1144 index_sequence_for<_Elements...>{})
1147 template<__eligible_tuple_like<tuple> _UTuple>
1148 requires (__constructible_from_tuple_like<_UTuple>())
1149 && (!__use_other_ctor<_UTuple>())
1150 && (__dangles_from_tuple_like<_UTuple>())
1151 tuple(_UTuple&&) = delete;
1154 // Allocator-extended constructors.
1156 template<typename _Alloc>
1158 explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
1159 tuple(allocator_arg_t __tag, const _Alloc& __a)
1160 requires (is_default_constructible_v<_Elements> && ...)
1161 : _Inherited(__tag, __a)
1164 template<typename _Alloc>
1165 constexpr explicit(!__convertible<const _Elements&...>())
1166 tuple(allocator_arg_t __tag, const _Alloc& __a,
1167 const _Elements&... __elements)
1168 requires (__constructible<const _Elements&...>())
1169 : _Inherited(__tag, __a, __elements...)
1172 template<typename _Alloc, typename... _UTypes>
1173 requires (__disambiguating_constraint<_UTypes...>())
1174 && (__constructible<_UTypes...>())
1175 && (!__dangles<_UTypes...>())
1176 constexpr explicit(!__convertible<_UTypes...>())
1177 tuple(allocator_arg_t __tag, const _Alloc& __a, _UTypes&&... __u)
1178 : _Inherited(__tag, __a, std::forward<_UTypes>(__u)...)
1181 template<typename _Alloc, typename... _UTypes>
1182 requires (__disambiguating_constraint<_UTypes...>())
1183 && (__constructible<_UTypes...>())
1184 && (__dangles<_UTypes...>())
1185 tuple(allocator_arg_t, const _Alloc&, _UTypes&&...) = delete;
1187 template<typename _Alloc>
1189 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __u)
1190 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__u))
1193 template<typename _Alloc>
1194 requires (__constructible<_Elements...>())
1196 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __u)
1197 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__u))
1200 template<typename _Alloc, typename... _UTypes>
1201 requires (__constructible<const _UTypes&...>())
1202 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1203 && (!__dangles<const _UTypes&...>())
1204 constexpr explicit(!__convertible<const _UTypes&...>())
1205 tuple(allocator_arg_t __tag, const _Alloc& __a,
1206 const tuple<_UTypes...>& __u)
1207 : _Inherited(__tag, __a,
1208 static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1211 template<typename _Alloc, typename... _UTypes>
1212 requires (__constructible<const _UTypes&...>())
1213 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1214 && (__dangles<const _UTypes&...>())
1215 tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&) = delete;
1217 template<typename _Alloc, typename... _UTypes>
1218 requires (__constructible<_UTypes...>())
1219 && (!__use_other_ctor<tuple<_UTypes...>>())
1220 && (!__dangles<_UTypes...>())
1221 constexpr explicit(!__use_other_ctor<tuple<_UTypes...>>())
1222 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>&& __u)
1223 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1226 template<typename _Alloc, typename... _UTypes>
1227 requires (__constructible<_UTypes...>())
1228 && (!__use_other_ctor<tuple<_UTypes...>>())
1229 && (__dangles<_UTypes...>())
1230 tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&&) = delete;
1232#if __cpp_lib_ranges_zip // >= C++23
1233 template<typename _Alloc, typename... _UTypes>
1234 requires (__constructible<_UTypes&...>())
1235 && (!__use_other_ctor<tuple<_UTypes...>&>())
1236 && (!__dangles<_UTypes&...>())
1237 constexpr explicit(!__convertible<_UTypes&...>())
1238 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>& __u)
1239 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1242 template<typename _Alloc, typename... _UTypes>
1243 requires (__constructible<_UTypes&...>())
1244 && (!__use_other_ctor<tuple<_UTypes...>&>())
1245 && (__dangles<_UTypes&...>())
1246 tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&) = delete;
1248 template<typename _Alloc, typename... _UTypes>
1249 requires (__constructible<const _UTypes...>())
1250 && (!__use_other_ctor<const tuple<_UTypes...>>())
1251 && (!__dangles<const _UTypes...>())
1252 constexpr explicit(!__convertible<const _UTypes...>())
1253 tuple(allocator_arg_t __tag, const _Alloc& __a,
1254 const tuple<_UTypes...>&& __u)
1255 : _Inherited(__tag, __a,
1256 static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1259 template<typename _Alloc, typename... _UTypes>
1260 requires (__constructible<const _UTypes...>())
1261 && (!__use_other_ctor<const tuple<_UTypes...>>())
1262 && (__dangles<const _UTypes...>())
1263 tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&&) = delete;
1266 template<typename _Alloc, typename _U1, typename _U2>
1267 requires (sizeof...(_Elements) == 2)
1268 && (__constructible<const _U1&, const _U2&>())
1269 && (!__dangles<const _U1&, const _U2&>())
1270 constexpr explicit(!__convertible<const _U1&, const _U2&>())
1271 tuple(allocator_arg_t __tag, const _Alloc& __a,
1272 const pair<_U1, _U2>& __u)
1273 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1274 : _Inherited(__tag, __a, __u.first, __u.second)
1277 template<typename _Alloc, typename _U1, typename _U2>
1278 requires (sizeof...(_Elements) == 2)
1279 && (__constructible<const _U1&, const _U2&>())
1280 && (__dangles<const _U1&, const _U2&>())
1281 tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&) = delete;
1283 template<typename _Alloc, typename _U1, typename _U2>
1284 requires (sizeof...(_Elements) == 2)
1285 && (__constructible<_U1, _U2>())
1286 && (!__dangles<_U1, _U2>())
1287 constexpr explicit(!__convertible<_U1, _U2>())
1288 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __u)
1289 noexcept(__nothrow_constructible<_U1, _U2>())
1290 : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1293 template<typename _Alloc, typename _U1, typename _U2>
1294 requires (sizeof...(_Elements) == 2)
1295 && (__constructible<_U1, _U2>())
1296 && (__dangles<_U1, _U2>())
1297 tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&) = delete;
1299#if __cpp_lib_ranges_zip // >= C++23
1300 template<typename _Alloc, typename _U1, typename _U2>
1301 requires (sizeof...(_Elements) == 2)
1302 && (__constructible<_U1&, _U2&>())
1303 && (!__dangles<_U1&, _U2&>())
1304 constexpr explicit(!__convertible<_U1&, _U2&>())
1305 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>& __u)
1306 noexcept(__nothrow_constructible<_U1&, _U2&>())
1307 : _Inherited(__tag, __a, __u.first, __u.second)
1310 template<typename _Alloc, typename _U1, typename _U2>
1311 requires (sizeof...(_Elements) == 2)
1312 && (__constructible<_U1&, _U2&>())
1313 && (__dangles<_U1&, _U2&>())
1314 tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&) = delete;
1316 template<typename _Alloc, typename _U1, typename _U2>
1317 requires (sizeof...(_Elements) == 2)
1318 && (__constructible<const _U1, const _U2>())
1319 && (!__dangles<const _U1, const _U2>())
1320 constexpr explicit(!__convertible<const _U1, const _U2>())
1321 tuple(allocator_arg_t __tag, const _Alloc& __a,
1322 const pair<_U1, _U2>&& __u)
1323 noexcept(__nothrow_constructible<const _U1, const _U2>())
1324 : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1327 template<typename _Alloc, typename _U1, typename _U2>
1328 requires (sizeof...(_Elements) == 2)
1329 && (__constructible<const _U1, const _U2>())
1330 && (__dangles<const _U1, const _U2>())
1331 tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&&) = delete;
1334#if __cpp_lib_tuple_like // >= C++23
1335 template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
1336 requires (__constructible_from_tuple_like<_UTuple>())
1337 && (!__use_other_ctor<_UTuple>())
1338 && (!__dangles_from_tuple_like<_UTuple>())
1339 constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
1340 tuple(allocator_arg_t __tag, const _Alloc& __a, _UTuple&& __u)
1341 : _Inherited(__tuple_like_tag_t{},
1342 __tag, __a, std::forward<_UTuple>(__u),
1343 index_sequence_for<_Elements...>{})
1346 template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
1347 requires (__constructible_from_tuple_like<_UTuple>())
1348 && (!__use_other_ctor<_UTuple>())
1349 && (__dangles_from_tuple_like<_UTuple>())
1350 tuple(allocator_arg_t, const _Alloc&, _UTuple&&) = delete;
1353#else // !(concepts && conditional_explicit)
1355 template<bool _Cond>
1356 using _TCC = _TupleConstraints<_Cond, _Elements...>;
1358 // Constraint for non-explicit default constructor
1359 template<bool _Dummy>
1360 using _ImplicitDefaultCtor = __enable_if_t<
1361 _TCC<_Dummy>::__is_implicitly_default_constructible(),
1364 // Constraint for explicit default constructor
1365 template<bool _Dummy>
1366 using _ExplicitDefaultCtor = __enable_if_t<
1367 _TCC<_Dummy>::__is_explicitly_default_constructible(),
1370 // Constraint for non-explicit constructors
1371 template<bool _Cond, typename... _Args>
1372 using _ImplicitCtor = __enable_if_t<
1373 _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
1376 // Constraint for non-explicit constructors
1377 template<bool _Cond, typename... _Args>
1378 using _ExplicitCtor = __enable_if_t<
1379 _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
1382 // Condition for noexcept-specifier of a constructor.
1383 template<typename... _UElements>
1384 static constexpr bool __nothrow_constructible()
1387 __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
1390 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1.
1391 template<typename _Up>
1392 static constexpr bool __valid_args()
1394 return sizeof...(_Elements) == 1
1395 && !is_same<tuple, __remove_cvref_t<_Up>>::value;
1398 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1.
1399 template<typename, typename, typename... _Tail>
1400 static constexpr bool __valid_args()
1401 { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); }
1403 /* Constraint for constructors with a tuple<UTypes...> parameter ensures
1404 * that the constructor is only viable when it would not interfere with
1405 * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&).
1406 * Such constructors are only viable if:
1407 * either sizeof...(Types) != 1,
1408 * or (when Types... expands to T and UTypes... expands to U)
1409 * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>,
1410 * and is_same_v<T, U> are all false.
1412 template<typename _Tuple, typename = tuple,
1413 typename = __remove_cvref_t<_Tuple>>
1414 struct _UseOtherCtor
1417 // If TUPLE is convertible to the single element in *this,
1418 // then TUPLE should match tuple(UTypes&&...) instead.
1419 template<typename _Tuple, typename _Tp, typename _Up>
1420 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>>
1421 : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>::type
1423 // If TUPLE and *this each have a single element of the same type,
1424 // then TUPLE should match a copy/move constructor instead.
1425 template<typename _Tuple, typename _Tp>
1426 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>>
1430 // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
1431 // and the single element in Types can be initialized from TUPLE,
1432 // or is the same type as tuple_element_t<0, TUPLE>.
1433 template<typename _Tuple>
1434 static constexpr bool __use_other_ctor()
1435 { return _UseOtherCtor<_Tuple>::value; }
1437 /// @cond undocumented
1438#undef __glibcxx_no_dangling_refs
1439#if __has_builtin(__reference_constructs_from_temporary) \
1440 && defined _GLIBCXX_DEBUG
1441 // Error if construction from U... would create a dangling ref.
1442# if __cpp_fold_expressions
1443# define __glibcxx_dangling_refs(U) \
1444 (__reference_constructs_from_temporary(_Elements, U) || ...)
1446# define __glibcxx_dangling_refs(U) \
1447 __or_<__bool_constant<__reference_constructs_from_temporary(_Elements, U) \
1450# define __glibcxx_no_dangling_refs(U) \
1451 static_assert(!__glibcxx_dangling_refs(U), \
1452 "std::tuple constructor creates a dangling reference")
1454# define __glibcxx_no_dangling_refs(U)
1459 template<typename _Dummy = void,
1460 _ImplicitDefaultCtor<is_void<_Dummy>::value> = true>
1463 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1466 template<typename _Dummy = void,
1467 _ExplicitDefaultCtor<is_void<_Dummy>::value> = false>
1470 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1473 template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1474 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1476 tuple(const _Elements&... __elements)
1477 noexcept(__nothrow_constructible<const _Elements&...>())
1478 : _Inherited(__elements...) { }
1480 template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1481 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1483 tuple(const _Elements&... __elements)
1484 noexcept(__nothrow_constructible<const _Elements&...>())
1485 : _Inherited(__elements...) { }
1487 template<typename... _UElements,
1488 bool _Valid = __valid_args<_UElements...>(),
1489 _ImplicitCtor<_Valid, _UElements...> = true>
1491 tuple(_UElements&&... __elements)
1492 noexcept(__nothrow_constructible<_UElements...>())
1493 : _Inherited(std::forward<_UElements>(__elements)...)
1494 { __glibcxx_no_dangling_refs(_UElements&&); }
1496 template<typename... _UElements,
1497 bool _Valid = __valid_args<_UElements...>(),
1498 _ExplicitCtor<_Valid, _UElements...> = false>
1500 tuple(_UElements&&... __elements)
1501 noexcept(__nothrow_constructible<_UElements...>())
1502 : _Inherited(std::forward<_UElements>(__elements)...)
1503 { __glibcxx_no_dangling_refs(_UElements&&); }
1505 constexpr tuple(const tuple&) = default;
1507 constexpr tuple(tuple&&) = default;
1509 template<typename... _UElements,
1510 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1511 && !__use_other_ctor<const tuple<_UElements...>&>(),
1512 _ImplicitCtor<_Valid, const _UElements&...> = true>
1514 tuple(const tuple<_UElements...>& __in)
1515 noexcept(__nothrow_constructible<const _UElements&...>())
1516 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1517 { __glibcxx_no_dangling_refs(const _UElements&); }
1519 template<typename... _UElements,
1520 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1521 && !__use_other_ctor<const tuple<_UElements...>&>(),
1522 _ExplicitCtor<_Valid, const _UElements&...> = false>
1524 tuple(const tuple<_UElements...>& __in)
1525 noexcept(__nothrow_constructible<const _UElements&...>())
1526 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1527 { __glibcxx_no_dangling_refs(const _UElements&); }
1529 template<typename... _UElements,
1530 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1531 && !__use_other_ctor<tuple<_UElements...>&&>(),
1532 _ImplicitCtor<_Valid, _UElements...> = true>
1534 tuple(tuple<_UElements...>&& __in)
1535 noexcept(__nothrow_constructible<_UElements...>())
1536 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1537 { __glibcxx_no_dangling_refs(_UElements&&); }
1539 template<typename... _UElements,
1540 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1541 && !__use_other_ctor<tuple<_UElements...>&&>(),
1542 _ExplicitCtor<_Valid, _UElements...> = false>
1544 tuple(tuple<_UElements...>&& __in)
1545 noexcept(__nothrow_constructible<_UElements...>())
1546 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1547 { __glibcxx_no_dangling_refs(_UElements&&); }
1549 // Allocator-extended constructors.
1551 template<typename _Alloc,
1552 _ImplicitDefaultCtor<is_object<_Alloc>::value> = true>
1553 _GLIBCXX20_CONSTEXPR
1554 tuple(allocator_arg_t __tag, const _Alloc& __a)
1555 : _Inherited(__tag, __a) { }
1557 template<typename _Alloc,
1558 _ExplicitDefaultCtor<is_object<_Alloc>::value> = false>
1559 _GLIBCXX20_CONSTEXPR
1561 tuple(allocator_arg_t __tag, const _Alloc& __a)
1562 : _Inherited(__tag, __a) { }
1564 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1565 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1566 _GLIBCXX20_CONSTEXPR
1567 tuple(allocator_arg_t __tag, const _Alloc& __a,
1568 const _Elements&... __elements)
1569 : _Inherited(__tag, __a, __elements...) { }
1571 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1572 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1573 _GLIBCXX20_CONSTEXPR
1575 tuple(allocator_arg_t __tag, const _Alloc& __a,
1576 const _Elements&... __elements)
1577 : _Inherited(__tag, __a, __elements...) { }
1579 template<typename _Alloc, typename... _UElements,
1580 bool _Valid = __valid_args<_UElements...>(),
1581 _ImplicitCtor<_Valid, _UElements...> = true>
1582 _GLIBCXX20_CONSTEXPR
1583 tuple(allocator_arg_t __tag, const _Alloc& __a,
1584 _UElements&&... __elements)
1585 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1586 { __glibcxx_no_dangling_refs(_UElements&&); }
1588 template<typename _Alloc, typename... _UElements,
1589 bool _Valid = __valid_args<_UElements...>(),
1590 _ExplicitCtor<_Valid, _UElements...> = false>
1591 _GLIBCXX20_CONSTEXPR
1593 tuple(allocator_arg_t __tag, const _Alloc& __a,
1594 _UElements&&... __elements)
1595 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1596 { __glibcxx_no_dangling_refs(_UElements&&); }
1598 template<typename _Alloc>
1599 _GLIBCXX20_CONSTEXPR
1600 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1601 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1603 template<typename _Alloc>
1604 _GLIBCXX20_CONSTEXPR
1605 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1606 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1608 template<typename _Alloc, typename... _UElements,
1609 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1610 && !__use_other_ctor<const tuple<_UElements...>&>(),
1611 _ImplicitCtor<_Valid, const _UElements&...> = true>
1612 _GLIBCXX20_CONSTEXPR
1613 tuple(allocator_arg_t __tag, const _Alloc& __a,
1614 const tuple<_UElements...>& __in)
1615 : _Inherited(__tag, __a,
1616 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1617 { __glibcxx_no_dangling_refs(const _UElements&); }
1619 template<typename _Alloc, typename... _UElements,
1620 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1621 && !__use_other_ctor<const tuple<_UElements...>&>(),
1622 _ExplicitCtor<_Valid, const _UElements&...> = false>
1623 _GLIBCXX20_CONSTEXPR
1625 tuple(allocator_arg_t __tag, const _Alloc& __a,
1626 const tuple<_UElements...>& __in)
1627 : _Inherited(__tag, __a,
1628 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1629 { __glibcxx_no_dangling_refs(const _UElements&); }
1631 template<typename _Alloc, typename... _UElements,
1632 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1633 && !__use_other_ctor<tuple<_UElements...>&&>(),
1634 _ImplicitCtor<_Valid, _UElements...> = true>
1635 _GLIBCXX20_CONSTEXPR
1636 tuple(allocator_arg_t __tag, const _Alloc& __a,
1637 tuple<_UElements...>&& __in)
1638 : _Inherited(__tag, __a,
1639 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1640 { __glibcxx_no_dangling_refs(_UElements&&); }
1642 template<typename _Alloc, typename... _UElements,
1643 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1644 && !__use_other_ctor<tuple<_UElements...>&&>(),
1645 _ExplicitCtor<_Valid, _UElements...> = false>
1646 _GLIBCXX20_CONSTEXPR
1648 tuple(allocator_arg_t __tag, const _Alloc& __a,
1649 tuple<_UElements...>&& __in)
1650 : _Inherited(__tag, __a,
1651 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1652 { __glibcxx_no_dangling_refs(_UElements&&); }
1653#endif // concepts && conditional_explicit
1657#if __cpp_concepts && __cpp_consteval // >= C++20
1659 template<typename... _UTypes>
1660 static consteval bool
1663 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1664 return __and_v<is_assignable<_Elements&, _UTypes>...>;
1669 template<typename... _UTypes>
1670 static consteval bool
1671 __nothrow_assignable()
1673 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1674 return __and_v<is_nothrow_assignable<_Elements&, _UTypes>...>;
1679#if __cpp_lib_ranges_zip // >= C++23
1680 template<typename... _UTypes>
1681 static consteval bool
1682 __const_assignable()
1684 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1685 return __and_v<is_assignable<const _Elements&, _UTypes>...>;
1691#if __cpp_lib_tuple_like // >= C++23
1692 template<typename _UTuple>
1693 static consteval bool
1694 __assignable_from_tuple_like()
1696 return []<size_t... _Is>(index_sequence<_Is...>) {
1697 return __assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1698 }(index_sequence_for<_Elements...>{});
1701 template<typename _UTuple>
1702 static consteval bool
1703 __const_assignable_from_tuple_like()
1705 return []<size_t... _Is>(index_sequence<_Is...>) {
1706 return __const_assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1707 }(index_sequence_for<_Elements...>{});
1713 tuple& operator=(const tuple& __u) = delete;
1716 operator=(const tuple& __u)
1717 noexcept(__nothrow_assignable<const _Elements&...>())
1718 requires (__assignable<const _Elements&...>())
1720 this->_M_assign(__u);
1725 operator=(tuple&& __u)
1726 noexcept(__nothrow_assignable<_Elements...>())
1727 requires (__assignable<_Elements...>())
1729 this->_M_assign(std::move(__u));
1733 template<typename... _UTypes>
1734 requires (__assignable<const _UTypes&...>())
1736 operator=(const tuple<_UTypes...>& __u)
1737 noexcept(__nothrow_assignable<const _UTypes&...>())
1739 this->_M_assign(__u);
1743 template<typename... _UTypes>
1744 requires (__assignable<_UTypes...>())
1746 operator=(tuple<_UTypes...>&& __u)
1747 noexcept(__nothrow_assignable<_UTypes...>())
1749 this->_M_assign(std::move(__u));
1753#if __cpp_lib_ranges_zip // >= C++23
1754 constexpr const tuple&
1755 operator=(const tuple& __u) const
1756 requires (__const_assignable<const _Elements&...>())
1758 this->_M_assign(__u);
1762 constexpr const tuple&
1763 operator=(tuple&& __u) const
1764 requires (__const_assignable<_Elements...>())
1766 this->_M_assign(std::move(__u));
1770 template<typename... _UTypes>
1771 constexpr const tuple&
1772 operator=(const tuple<_UTypes...>& __u) const
1773 requires (__const_assignable<const _UTypes&...>())
1775 this->_M_assign(__u);
1779 template<typename... _UTypes>
1780 constexpr const tuple&
1781 operator=(tuple<_UTypes...>&& __u) const
1782 requires (__const_assignable<_UTypes...>())
1784 this->_M_assign(std::move(__u));
1789 template<typename _U1, typename _U2>
1790 requires (__assignable<const _U1&, const _U2&>())
1792 operator=(const pair<_U1, _U2>& __u)
1793 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1795 this->_M_head(*this) = __u.first;
1796 this->_M_tail(*this)._M_head(*this) = __u.second;
1800 template<typename _U1, typename _U2>
1801 requires (__assignable<_U1, _U2>())
1803 operator=(pair<_U1, _U2>&& __u)
1804 noexcept(__nothrow_assignable<_U1, _U2>())
1806 this->_M_head(*this) = std::forward<_U1>(__u.first);
1807 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1811#if __cpp_lib_ranges_zip // >= C++23
1812 template<typename _U1, typename _U2>
1813 requires (__const_assignable<const _U1&, const _U2>())
1814 constexpr const tuple&
1815 operator=(const pair<_U1, _U2>& __u) const
1817 this->_M_head(*this) = __u.first;
1818 this->_M_tail(*this)._M_head(*this) = __u.second;
1822 template<typename _U1, typename _U2>
1823 requires (__const_assignable<_U1, _U2>())
1824 constexpr const tuple&
1825 operator=(pair<_U1, _U2>&& __u) const
1827 this->_M_head(*this) = std::forward<_U1>(__u.first);
1828 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1833#if __cpp_lib_tuple_like // >= C++23
1834 template<__eligible_tuple_like<tuple> _UTuple>
1835 requires (__assignable_from_tuple_like<_UTuple>())
1837 operator=(_UTuple&& __u)
1839 this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1843 template<__eligible_tuple_like<tuple> _UTuple>
1844 requires (__const_assignable_from_tuple_like<_UTuple>())
1845 constexpr const tuple&
1846 operator=(_UTuple&& __u) const
1848 this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1852 template<__tuple_like _UTuple>
1853 requires (!__is_tuple_v<_UTuple>)
1854 friend constexpr bool
1855 operator==(const tuple& __t, const _UTuple& __u)
1857 static_assert(sizeof...(_Elements) == tuple_size_v<_UTuple>,
1858 "tuple objects can only be compared if they have equal sizes.");
1859 return [&]<size_t... _Is>(index_sequence<_Is...>) {
1860 return (bool(std::get<_Is>(__t) == std::get<_Is>(__u))
1862 }(index_sequence_for<_Elements...>{});
1865 template<__tuple_like _UTuple,
1866 typename = make_index_sequence<tuple_size_v<_UTuple>>>
1867 struct __tuple_like_common_comparison_category;
1869 template<__tuple_like _UTuple, size_t... _Is>
1871 { typename void_t<__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>; }
1872 struct __tuple_like_common_comparison_category<_UTuple, index_sequence<_Is...>>
1874 using type = common_comparison_category_t
1875 <__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>;
1878 template<__tuple_like _UTuple>
1879 requires (!__is_tuple_v<_UTuple>)
1880 friend constexpr typename __tuple_like_common_comparison_category<_UTuple>::type
1881 operator<=>(const tuple& __t, const _UTuple& __u)
1883 using _Cat = typename __tuple_like_common_comparison_category<_UTuple>::type;
1884 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Elements...>());
1888#else // ! (concepts && consteval)
1891 template<typename... _UElements>
1893 __enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
1895 { return __and_<is_assignable<_Elements&, _UElements>...>::value; }
1897 // Condition for noexcept-specifier of an assignment operator.
1898 template<typename... _UElements>
1899 static constexpr bool __nothrow_assignable()
1902 __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
1907 _GLIBCXX20_CONSTEXPR
1909 operator=(__conditional_t<__assignable<const _Elements&...>(),
1911 const __nonesuch&> __in)
1912 noexcept(__nothrow_assignable<const _Elements&...>())
1914 this->_M_assign(__in);
1918 _GLIBCXX20_CONSTEXPR
1920 operator=(__conditional_t<__assignable<_Elements...>(),
1923 noexcept(__nothrow_assignable<_Elements...>())
1925 this->_M_assign(std::move(__in));
1929 template<typename... _UElements>
1930 _GLIBCXX20_CONSTEXPR
1931 __enable_if_t<__assignable<const _UElements&...>(), tuple&>
1932 operator=(const tuple<_UElements...>& __in)
1933 noexcept(__nothrow_assignable<const _UElements&...>())
1935 this->_M_assign(__in);
1939 template<typename... _UElements>
1940 _GLIBCXX20_CONSTEXPR
1941 __enable_if_t<__assignable<_UElements...>(), tuple&>
1942 operator=(tuple<_UElements...>&& __in)
1943 noexcept(__nothrow_assignable<_UElements...>())
1945 this->_M_assign(std::move(__in));
1948#endif // concepts && consteval
1951 _GLIBCXX20_CONSTEXPR
1954 noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
1955 { _Inherited::_M_swap(__in); }
1957#if __cpp_lib_ranges_zip // >= C++23
1958 // As an extension, we constrain the const swap member function in order
1959 // to continue accepting explicit instantiation of tuples whose elements
1960 // are not all const swappable. Without this constraint, such an
1961 // explicit instantiation would also instantiate the ill-formed body of
1962 // this function and yield a hard error. This constraint shouldn't
1963 // affect the behavior of valid programs.
1965 swap(const tuple& __in) const
1966 noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
1967 requires (is_swappable_v<const _Elements> && ...)
1968 { _Inherited::_M_swap(__in); }
1972#if __cpp_deduction_guides >= 201606
1973 template<typename... _UTypes>
1974 tuple(_UTypes...) -> tuple<_UTypes...>;
1975 template<typename _T1, typename _T2>
1976 tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
1977 template<typename _Alloc, typename... _UTypes>
1978 tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
1979 template<typename _Alloc, typename _T1, typename _T2>
1980 tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
1981 template<typename _Alloc, typename... _UTypes>
1982 tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
1985 // Explicit specialization, zero-element tuple.
1990 _GLIBCXX20_CONSTEXPR
1991 void swap(tuple&) noexcept { /* no-op */ }
1992#if __cpp_lib_ranges_zip // >= C++23
1993 constexpr void swap(const tuple&) const noexcept { /* no-op */ }
1995 // We need the default since we're going to define no-op
1996 // allocator constructors.
1998 // No-op allocator constructors.
1999 template<typename _Alloc>
2000 _GLIBCXX20_CONSTEXPR
2001 tuple(allocator_arg_t, const _Alloc&) noexcept { }
2002 template<typename _Alloc>
2003 _GLIBCXX20_CONSTEXPR
2004 tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
2007#if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20
2008 /// Partial specialization, 2-element tuple.
2009 /// Includes construction and assignment from a pair.
2010 template<typename _T1, typename _T2>
2011 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
2013 typedef _Tuple_impl<0, _T1, _T2> _Inherited;
2015 // Constraint for non-explicit default constructor
2016 template<bool _Dummy, typename _U1, typename _U2>
2017 using _ImplicitDefaultCtor = __enable_if_t<
2018 _TupleConstraints<_Dummy, _U1, _U2>::
2019 __is_implicitly_default_constructible(),
2022 // Constraint for explicit default constructor
2023 template<bool _Dummy, typename _U1, typename _U2>
2024 using _ExplicitDefaultCtor = __enable_if_t<
2025 _TupleConstraints<_Dummy, _U1, _U2>::
2026 __is_explicitly_default_constructible(),
2029 template<bool _Dummy>
2030 using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
2032 // Constraint for non-explicit constructors
2033 template<bool _Cond, typename _U1, typename _U2>
2034 using _ImplicitCtor = __enable_if_t<
2035 _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
2038 // Constraint for non-explicit constructors
2039 template<bool _Cond, typename _U1, typename _U2>
2040 using _ExplicitCtor = __enable_if_t<
2041 _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
2044 template<typename _U1, typename _U2>
2045 static constexpr bool __assignable()
2047 return __and_<is_assignable<_T1&, _U1>,
2048 is_assignable<_T2&, _U2>>::value;
2051 template<typename _U1, typename _U2>
2052 static constexpr bool __nothrow_assignable()
2054 return __and_<is_nothrow_assignable<_T1&, _U1>,
2055 is_nothrow_assignable<_T2&, _U2>>::value;
2058 template<typename _U1, typename _U2>
2059 static constexpr bool __nothrow_constructible()
2061 return __and_<is_nothrow_constructible<_T1, _U1>,
2062 is_nothrow_constructible<_T2, _U2>>::value;
2065 static constexpr bool __nothrow_default_constructible()
2067 return __and_<is_nothrow_default_constructible<_T1>,
2068 is_nothrow_default_constructible<_T2>>::value;
2071 template<typename _U1>
2072 static constexpr bool __is_alloc_arg()
2073 { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
2075 /// @cond undocumented
2076#undef __glibcxx_no_dangling_refs
2077 // Error if construction from _U1 and _U2 would create a dangling ref.
2078#if __has_builtin(__reference_constructs_from_temporary) \
2079 && defined _GLIBCXX_DEBUG
2080# define __glibcxx_no_dangling_refs(_U1, _U2) \
2081 static_assert(!__reference_constructs_from_temporary(_T1, _U1) \
2082 && !__reference_constructs_from_temporary(_T2, _U2), \
2083 "std::tuple constructor creates a dangling reference")
2085# define __glibcxx_no_dangling_refs(_U1, _U2)
2090 template<bool _Dummy = true,
2091 _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
2094 noexcept(__nothrow_default_constructible())
2097 template<bool _Dummy = true,
2098 _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
2101 noexcept(__nothrow_default_constructible())
2104 template<bool _Dummy = true,
2105 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2107 tuple(const _T1& __a1, const _T2& __a2)
2108 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2109 : _Inherited(__a1, __a2) { }
2111 template<bool _Dummy = true,
2112 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2114 tuple(const _T1& __a1, const _T2& __a2)
2115 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2116 : _Inherited(__a1, __a2) { }
2118 template<typename _U1, typename _U2,
2119 _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
2121 tuple(_U1&& __a1, _U2&& __a2)
2122 noexcept(__nothrow_constructible<_U1, _U2>())
2123 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2124 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2126 template<typename _U1, typename _U2,
2127 _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
2129 tuple(_U1&& __a1, _U2&& __a2)
2130 noexcept(__nothrow_constructible<_U1, _U2>())
2131 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2132 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2134 constexpr tuple(const tuple&) = default;
2136 constexpr tuple(tuple&&) = default;
2138 template<typename _U1, typename _U2,
2139 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2141 tuple(const tuple<_U1, _U2>& __in)
2142 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2143 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2144 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2146 template<typename _U1, typename _U2,
2147 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2149 tuple(const tuple<_U1, _U2>& __in)
2150 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2151 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2152 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2154 template<typename _U1, typename _U2,
2155 _ImplicitCtor<true, _U1, _U2> = true>
2157 tuple(tuple<_U1, _U2>&& __in)
2158 noexcept(__nothrow_constructible<_U1, _U2>())
2159 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2160 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2162 template<typename _U1, typename _U2,
2163 _ExplicitCtor<true, _U1, _U2> = false>
2165 tuple(tuple<_U1, _U2>&& __in)
2166 noexcept(__nothrow_constructible<_U1, _U2>())
2167 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2168 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2170 template<typename _U1, typename _U2,
2171 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2173 tuple(const pair<_U1, _U2>& __in)
2174 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2175 : _Inherited(__in.first, __in.second)
2176 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2178 template<typename _U1, typename _U2,
2179 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2181 tuple(const pair<_U1, _U2>& __in)
2182 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2183 : _Inherited(__in.first, __in.second)
2184 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2186 template<typename _U1, typename _U2,
2187 _ImplicitCtor<true, _U1, _U2> = true>
2189 tuple(pair<_U1, _U2>&& __in)
2190 noexcept(__nothrow_constructible<_U1, _U2>())
2191 : _Inherited(std::forward<_U1>(__in.first),
2192 std::forward<_U2>(__in.second))
2193 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2195 template<typename _U1, typename _U2,
2196 _ExplicitCtor<true, _U1, _U2> = false>
2198 tuple(pair<_U1, _U2>&& __in)
2199 noexcept(__nothrow_constructible<_U1, _U2>())
2200 : _Inherited(std::forward<_U1>(__in.first),
2201 std::forward<_U2>(__in.second))
2202 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2204 // Allocator-extended constructors.
2206 template<typename _Alloc,
2207 _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
2208 _GLIBCXX20_CONSTEXPR
2209 tuple(allocator_arg_t __tag, const _Alloc& __a)
2210 : _Inherited(__tag, __a) { }
2212 template<typename _Alloc,
2213 _ExplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = false>
2214 _GLIBCXX20_CONSTEXPR
2216 tuple(allocator_arg_t __tag, const _Alloc& __a)
2217 : _Inherited(__tag, __a) { }
2219 template<typename _Alloc, bool _Dummy = true,
2220 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2221 _GLIBCXX20_CONSTEXPR
2222 tuple(allocator_arg_t __tag, const _Alloc& __a,
2223 const _T1& __a1, const _T2& __a2)
2224 : _Inherited(__tag, __a, __a1, __a2) { }
2226 template<typename _Alloc, bool _Dummy = true,
2227 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2229 _GLIBCXX20_CONSTEXPR
2230 tuple(allocator_arg_t __tag, const _Alloc& __a,
2231 const _T1& __a1, const _T2& __a2)
2232 : _Inherited(__tag, __a, __a1, __a2) { }
2234 template<typename _Alloc, typename _U1, typename _U2,
2235 _ImplicitCtor<true, _U1, _U2> = true>
2236 _GLIBCXX20_CONSTEXPR
2237 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
2238 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2239 std::forward<_U2>(__a2))
2240 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2242 template<typename _Alloc, typename _U1, typename _U2,
2243 _ExplicitCtor<true, _U1, _U2> = false>
2245 _GLIBCXX20_CONSTEXPR
2246 tuple(allocator_arg_t __tag, const _Alloc& __a,
2247 _U1&& __a1, _U2&& __a2)
2248 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2249 std::forward<_U2>(__a2))
2250 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2252 template<typename _Alloc>
2253 _GLIBCXX20_CONSTEXPR
2254 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
2255 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
2257 template<typename _Alloc>
2258 _GLIBCXX20_CONSTEXPR
2259 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
2260 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
2262 template<typename _Alloc, typename _U1, typename _U2,
2263 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2264 _GLIBCXX20_CONSTEXPR
2265 tuple(allocator_arg_t __tag, const _Alloc& __a,
2266 const tuple<_U1, _U2>& __in)
2267 : _Inherited(__tag, __a,
2268 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2269 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2271 template<typename _Alloc, typename _U1, typename _U2,
2272 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2274 _GLIBCXX20_CONSTEXPR
2275 tuple(allocator_arg_t __tag, const _Alloc& __a,
2276 const tuple<_U1, _U2>& __in)
2277 : _Inherited(__tag, __a,
2278 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2279 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2281 template<typename _Alloc, typename _U1, typename _U2,
2282 _ImplicitCtor<true, _U1, _U2> = true>
2283 _GLIBCXX20_CONSTEXPR
2284 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2285 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2286 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2288 template<typename _Alloc, typename _U1, typename _U2,
2289 _ExplicitCtor<true, _U1, _U2> = false>
2291 _GLIBCXX20_CONSTEXPR
2292 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2293 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2294 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2296 template<typename _Alloc, typename _U1, typename _U2,
2297 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2298 _GLIBCXX20_CONSTEXPR
2299 tuple(allocator_arg_t __tag, const _Alloc& __a,
2300 const pair<_U1, _U2>& __in)
2301 : _Inherited(__tag, __a, __in.first, __in.second)
2302 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2304 template<typename _Alloc, typename _U1, typename _U2,
2305 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2307 _GLIBCXX20_CONSTEXPR
2308 tuple(allocator_arg_t __tag, const _Alloc& __a,
2309 const pair<_U1, _U2>& __in)
2310 : _Inherited(__tag, __a, __in.first, __in.second)
2311 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2313 template<typename _Alloc, typename _U1, typename _U2,
2314 _ImplicitCtor<true, _U1, _U2> = true>
2315 _GLIBCXX20_CONSTEXPR
2316 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2317 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2318 std::forward<_U2>(__in.second))
2319 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2321 template<typename _Alloc, typename _U1, typename _U2,
2322 _ExplicitCtor<true, _U1, _U2> = false>
2324 _GLIBCXX20_CONSTEXPR
2325 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2326 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2327 std::forward<_U2>(__in.second))
2328 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2330 // Tuple assignment.
2332 _GLIBCXX20_CONSTEXPR
2334 operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
2336 const __nonesuch&> __in)
2337 noexcept(__nothrow_assignable<const _T1&, const _T2&>())
2339 this->_M_assign(__in);
2343 _GLIBCXX20_CONSTEXPR
2345 operator=(__conditional_t<__assignable<_T1, _T2>(),
2348 noexcept(__nothrow_assignable<_T1, _T2>())
2350 this->_M_assign(std::move(__in));
2354 template<typename _U1, typename _U2>
2355 _GLIBCXX20_CONSTEXPR
2356 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2357 operator=(const tuple<_U1, _U2>& __in)
2358 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2360 this->_M_assign(__in);
2364 template<typename _U1, typename _U2>
2365 _GLIBCXX20_CONSTEXPR
2366 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2367 operator=(tuple<_U1, _U2>&& __in)
2368 noexcept(__nothrow_assignable<_U1, _U2>())
2370 this->_M_assign(std::move(__in));
2374 template<typename _U1, typename _U2>
2375 _GLIBCXX20_CONSTEXPR
2376 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2377 operator=(const pair<_U1, _U2>& __in)
2378 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2380 this->_M_head(*this) = __in.first;
2381 this->_M_tail(*this)._M_head(*this) = __in.second;
2385 template<typename _U1, typename _U2>
2386 _GLIBCXX20_CONSTEXPR
2387 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2388 operator=(pair<_U1, _U2>&& __in)
2389 noexcept(__nothrow_assignable<_U1, _U2>())
2391 this->_M_head(*this) = std::forward<_U1>(__in.first);
2392 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
2396 _GLIBCXX20_CONSTEXPR
2399 noexcept(__and_<__is_nothrow_swappable<_T1>,
2400 __is_nothrow_swappable<_T2>>::value)
2401 { _Inherited::_M_swap(__in); }
2403#endif // concepts && conditional_explicit
2405 /// class tuple_size
2406 template<typename... _Elements>
2407 struct tuple_size<tuple<_Elements...>>
2408 : public integral_constant<size_t, sizeof...(_Elements)> { };
2410#if __cplusplus >= 201703L
2411 template<typename... _Types>
2412 inline constexpr size_t tuple_size_v<tuple<_Types...>>
2413 = sizeof...(_Types);
2415 template<typename... _Types>
2416 inline constexpr size_t tuple_size_v<const tuple<_Types...>>
2417 = sizeof...(_Types);
2420 /// Trait to get the Ith element type from a tuple.
2421 template<size_t __i, typename... _Types>
2422 struct tuple_element<__i, tuple<_Types...>>
2424 static_assert(__i < sizeof...(_Types), "tuple index must be in range");
2426 using type = typename _Nth_type<__i, _Types...>::type;
2429 template<size_t __i, typename _Head, typename... _Tail>
2431 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2432 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2434 template<size_t __i, typename _Head, typename... _Tail>
2435 constexpr const _Head&
2436 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2437 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2439 // Deleted overload to improve diagnostics for invalid indices
2440 template<size_t __i, typename... _Types>
2441 __enable_if_t<(__i >= sizeof...(_Types))>
2442 __get_helper(const tuple<_Types...>&) = delete;
2444 /// Return a reference to the ith element of a tuple.
2445 template<size_t __i, typename... _Elements>
2446 constexpr __tuple_element_t<__i, tuple<_Elements...>>&
2447 get(tuple<_Elements...>& __t) noexcept
2448 { return std::__get_helper<__i>(__t); }
2450 /// Return a const reference to the ith element of a const tuple.
2451 template<size_t __i, typename... _Elements>
2452 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
2453 get(const tuple<_Elements...>& __t) noexcept
2454 { return std::__get_helper<__i>(__t); }
2456 /// Return an rvalue reference to the ith element of a tuple rvalue.
2457 template<size_t __i, typename... _Elements>
2458 constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
2459 get(tuple<_Elements...>&& __t) noexcept
2461 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2462 return std::forward<__element_type>(std::__get_helper<__i>(__t));
2465 /// Return a const rvalue reference to the ith element of a const tuple rvalue.
2466 template<size_t __i, typename... _Elements>
2467 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
2468 get(const tuple<_Elements...>&& __t) noexcept
2470 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2471 return std::forward<const __element_type>(std::__get_helper<__i>(__t));
2474 /// @cond undocumented
2475 // Deleted overload chosen for invalid indices.
2476 template<size_t __i, typename... _Elements>
2477 constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
2478 get(const tuple<_Elements...>&) = delete;
2481#ifdef __cpp_lib_tuples_by_type // C++ >= 14
2482 /// Return a reference to the unique element of type _Tp of a tuple.
2483 template <typename _Tp, typename... _Types>
2485 get(tuple<_Types...>& __t) noexcept
2487 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2488 static_assert(__idx < sizeof...(_Types),
2489 "the type T in std::get<T> must occur exactly once in the tuple");
2490 return std::__get_helper<__idx>(__t);
2493 /// Return a reference to the unique element of type _Tp of a tuple rvalue.
2494 template <typename _Tp, typename... _Types>
2496 get(tuple<_Types...>&& __t) noexcept
2498 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2499 static_assert(__idx < sizeof...(_Types),
2500 "the type T in std::get<T> must occur exactly once in the tuple");
2501 return std::forward<_Tp>(std::__get_helper<__idx>(__t));
2504 /// Return a const reference to the unique element of type _Tp of a tuple.
2505 template <typename _Tp, typename... _Types>
2506 constexpr const _Tp&
2507 get(const tuple<_Types...>& __t) noexcept
2509 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2510 static_assert(__idx < sizeof...(_Types),
2511 "the type T in std::get<T> must occur exactly once in the tuple");
2512 return std::__get_helper<__idx>(__t);
2515 /// Return a const reference to the unique element of type _Tp of
2516 /// a const tuple rvalue.
2517 template <typename _Tp, typename... _Types>
2518 constexpr const _Tp&&
2519 get(const tuple<_Types...>&& __t) noexcept
2521 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2522 static_assert(__idx < sizeof...(_Types),
2523 "the type T in std::get<T> must occur exactly once in the tuple");
2524 return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
2528 // This class performs the comparison operations on tuples
2529 template<typename _Tp, typename _Up, size_t __i, size_t __size>
2530 struct __tuple_compare
2532 static constexpr bool
2533 __eq(const _Tp& __t, const _Up& __u)
2535 return bool(std::get<__i>(__t) == std::get<__i>(__u))
2536 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
2539 static constexpr bool
2540 __less(const _Tp& __t, const _Up& __u)
2542 return bool(std::get<__i>(__t) < std::get<__i>(__u))
2543 || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
2544 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
2548 template<typename _Tp, typename _Up, size_t __size>
2549 struct __tuple_compare<_Tp, _Up, __size, __size>
2551 static constexpr bool
2552 __eq(const _Tp&, const _Up&) { return true; }
2554 static constexpr bool
2555 __less(const _Tp&, const _Up&) { return false; }
2558 template<typename... _TElements, typename... _UElements>
2560 operator==(const tuple<_TElements...>& __t,
2561 const tuple<_UElements...>& __u)
2563 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2564 "tuple objects can only be compared if they have equal sizes.");
2565 using __compare = __tuple_compare<tuple<_TElements...>,
2566 tuple<_UElements...>,
2567 0, sizeof...(_TElements)>;
2568 return __compare::__eq(__t, __u);
2571#if __cpp_lib_three_way_comparison
2572 template<typename _Cat, typename _Tp, typename _Up>
2574 __tuple_cmp(const _Tp&, const _Up&, index_sequence<>)
2575 { return _Cat::equivalent; }
2577 template<typename _Cat, typename _Tp, typename _Up,
2578 size_t _Idx0, size_t... _Idxs>
2580 __tuple_cmp(const _Tp& __t, const _Up& __u,
2581 index_sequence<_Idx0, _Idxs...>)
2584 = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u));
2587 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>());
2590 template<typename... _Tps, typename... _Ups>
2592 common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
2593 operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
2596 = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
2597 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
2600 template<typename... _TElements, typename... _UElements>
2602 operator<(const tuple<_TElements...>& __t,
2603 const tuple<_UElements...>& __u)
2605 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2606 "tuple objects can only be compared if they have equal sizes.");
2607 using __compare = __tuple_compare<tuple<_TElements...>,
2608 tuple<_UElements...>,
2609 0, sizeof...(_TElements)>;
2610 return __compare::__less(__t, __u);
2613 template<typename... _TElements, typename... _UElements>
2615 operator!=(const tuple<_TElements...>& __t,
2616 const tuple<_UElements...>& __u)
2617 { return !(__t == __u); }
2619 template<typename... _TElements, typename... _UElements>
2621 operator>(const tuple<_TElements...>& __t,
2622 const tuple<_UElements...>& __u)
2623 { return __u < __t; }
2625 template<typename... _TElements, typename... _UElements>
2627 operator<=(const tuple<_TElements...>& __t,
2628 const tuple<_UElements...>& __u)
2629 { return !(__u < __t); }
2631 template<typename... _TElements, typename... _UElements>
2633 operator>=(const tuple<_TElements...>& __t,
2634 const tuple<_UElements...>& __u)
2635 { return !(__t < __u); }
2636#endif // three_way_comparison
2639 /// Create a tuple containing copies of the arguments
2640 template<typename... _Elements>
2641 constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
2642 make_tuple(_Elements&&... __args)
2644 typedef tuple<typename __decay_and_strip<_Elements>::__type...>
2646 return __result_type(std::forward<_Elements>(__args)...);
2649 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2650 // 2275. Why is forward_as_tuple not constexpr?
2651 /// Create a tuple of lvalue or rvalue references to the arguments
2652 template<typename... _Elements>
2653 constexpr tuple<_Elements&&...>
2654 forward_as_tuple(_Elements&&... __args) noexcept
2655 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2657 /// @cond undocumented
2658 template<size_t, typename, typename, size_t>
2659 struct __make_tuple_impl;
2661 template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
2662 struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
2663 : __make_tuple_impl<_Idx + 1,
2664 tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
2668 template<size_t _Nm, typename _Tuple, typename... _Tp>
2669 struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
2671 typedef tuple<_Tp...> __type;
2674 template<typename _Tuple>
2675 struct __do_make_tuple
2676 : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
2679 // Returns the std::tuple equivalent of a tuple-like type.
2680 template<typename _Tuple>
2682 : public __do_make_tuple<__remove_cvref_t<_Tuple>>
2685 // Combines several std::tuple's into a single one.
2686 template<typename...>
2687 struct __combine_tuples;
2690 struct __combine_tuples<>
2692 typedef tuple<> __type;
2695 template<typename... _Ts>
2696 struct __combine_tuples<tuple<_Ts...>>
2698 typedef tuple<_Ts...> __type;
2701 template<typename... _T1s, typename... _T2s, typename... _Rem>
2702 struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
2704 typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
2705 _Rem...>::__type __type;
2708 // Computes the result type of tuple_cat given a set of tuple-like types.
2709 template<typename... _Tpls>
2710 struct __tuple_cat_result
2712 typedef typename __combine_tuples
2713 <typename __make_tuple<_Tpls>::__type...>::__type __type;
2716 // Helper to determine the index set for the first tuple-like
2717 // type of a given set.
2718 template<typename...>
2719 struct __make_1st_indices;
2722 struct __make_1st_indices<>
2724 typedef _Index_tuple<> __type;
2727 template<typename _Tp, typename... _Tpls>
2728 struct __make_1st_indices<_Tp, _Tpls...>
2730 typedef typename _Build_index_tuple<tuple_size<
2731 typename remove_reference<_Tp>::type>::value>::__type __type;
2734 // Performs the actual concatenation by step-wise expanding tuple-like
2735 // objects into the elements, which are finally forwarded into the
2737 template<typename _Ret, typename _Indices, typename... _Tpls>
2738 struct __tuple_concater;
2740 template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2741 struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2743 template<typename... _Us>
2744 static constexpr _Ret
2745 _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2747 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2748 typedef __tuple_concater<_Ret, __idx, _Tpls...> __next;
2749 return __next::_S_do(std::forward<_Tpls>(__tps)...,
2750 std::forward<_Us>(__us)...,
2751 std::get<_Is>(std::forward<_Tp>(__tp))...);
2755 template<typename _Ret>
2756 struct __tuple_concater<_Ret, _Index_tuple<>>
2758 template<typename... _Us>
2759 static constexpr _Ret
2760 _S_do(_Us&&... __us)
2762 return _Ret(std::forward<_Us>(__us)...);
2766 template<typename... _Tps>
2767 struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2771 /// Create a `tuple` containing all elements from multiple tuple-like objects
2772#if __cpp_lib_tuple_like // >= C++23
2773 template<__tuple_like... _Tpls>
2775 template<typename... _Tpls, typename = typename
2776 enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2779 tuple_cat(_Tpls&&... __tpls)
2780 -> typename __tuple_cat_result<_Tpls...>::__type
2782 typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2783 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2784 typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2785 return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2788 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2789 // 2301. Why is tie not constexpr?
2790 /// Return a tuple of lvalue references bound to the arguments
2791 template<typename... _Elements>
2792 constexpr tuple<_Elements&...>
2793 tie(_Elements&... __args) noexcept
2794 { return tuple<_Elements&...>(__args...); }
2796 /// Exchange the values of two tuples
2797 template<typename... _Elements>
2798 _GLIBCXX20_CONSTEXPR
2800#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2801 // Constrained free swap overload, see p0185r1
2802 typename enable_if<__and_<__is_swappable<_Elements>...>::value
2807 swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
2808 noexcept(noexcept(__x.swap(__y)))
2811#if __cpp_lib_ranges_zip // >= C++23
2812 template<typename... _Elements>
2813 requires (is_swappable_v<const _Elements> && ...)
2815 swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2816 noexcept(noexcept(__x.swap(__y)))
2820#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2821 /// Exchange the values of two const tuples (if const elements can be swapped)
2822 template<typename... _Elements>
2823 _GLIBCXX20_CONSTEXPR
2824 typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2825 swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2828 // A class (and instance) which can be used in 'tie' when an element
2829 // of a tuple is not required.
2830 // _GLIBCXX14_CONSTEXPR
2831 // 2933. PR for LWG 2773 could be clearer
2832 struct _Swallow_assign
2835 _GLIBCXX14_CONSTEXPR const _Swallow_assign&
2836 operator=(const _Tp&) const
2840 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2841 // 2773. Making std::ignore constexpr
2842 /** Used with `std::tie` to ignore an element of a tuple
2844 * When using `std::tie` to assign the elements of a tuple to variables,
2845 * unwanted elements can be ignored by using `std::ignore`. For example:
2849 * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3);
2852 * This assignment will perform `x=1; std::ignore=2; y=3;` which results
2853 * in the second element being ignored.
2857 _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{};
2859 /// Partial specialization for tuples
2860 template<typename... _Types, typename _Alloc>
2861 struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2863 // See stl_pair.h...
2864 /** "piecewise construction" using a tuple of arguments for each member.
2866 * @param __first Arguments for the first member of the pair.
2867 * @param __second Arguments for the second member of the pair.
2869 * The elements of each tuple will be used as the constructor arguments
2870 * for the data members of the pair.
2872 template<class _T1, class _T2>
2873 template<typename... _Args1, typename... _Args2>
2874 _GLIBCXX20_CONSTEXPR
2877 pair(piecewise_construct_t,
2878 tuple<_Args1...> __first, tuple<_Args2...> __second)
2879 : pair(__first, __second,
2880 typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2881 typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2884 template<class _T1, class _T2>
2885 template<typename... _Args1, size_t... _Indexes1,
2886 typename... _Args2, size_t... _Indexes2>
2887 _GLIBCXX20_CONSTEXPR inline
2889 pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2890 _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2891 : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2892 second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2895#if defined(__cpp_lib_apply) || defined(__cpp_lib_make_from_tuple) // C++ >= 17
2896 // Unpack a std::tuple into a type trait and use its value.
2897 // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2898 // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2899 // Otherwise the result is false (because we don't know if std::get throws).
2900 template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2901 inline constexpr bool __unpack_std_tuple = false;
2903 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2904 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2905 = _Trait<_Tp, _Up...>::value;
2907 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2908 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2909 = _Trait<_Tp, _Up&...>::value;
2911 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2912 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2913 = _Trait<_Tp, const _Up...>::value;
2915 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2916 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2917 = _Trait<_Tp, const _Up&...>::value;
2920#ifdef __cpp_lib_apply // C++ >= 17
2921 template <typename _Fn, typename _Tuple, size_t... _Idx>
2922 constexpr decltype(auto)
2923 __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2925 return std::__invoke(std::forward<_Fn>(__f),
2926 std::get<_Idx>(std::forward<_Tuple>(__t))...);
2929#if __cpp_lib_tuple_like // >= C++23
2930 template <typename _Fn, __tuple_like _Tuple>
2932 template <typename _Fn, typename _Tuple>
2934 constexpr decltype(auto)
2935 apply(_Fn&& __f, _Tuple&& __t)
2936 noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2939 = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2940 return std::__apply_impl(std::forward<_Fn>(__f),
2941 std::forward<_Tuple>(__t),
2946#ifdef __cpp_lib_make_from_tuple // C++ >= 17
2947 template <typename _Tp, typename _Tuple, size_t... _Idx>
2949 __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
2950 { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
2952#if __cpp_lib_tuple_like // >= C++23
2953 template <typename _Tp, __tuple_like _Tuple>
2955 template <typename _Tp, typename _Tuple>
2958 make_from_tuple(_Tuple&& __t)
2959 noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
2961 constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
2962#if __has_builtin(__reference_constructs_from_temporary)
2963 if constexpr (__n == 1)
2965 using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
2966 static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
2969 return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
2970 make_index_sequence<__n>{});
2974#if __cpp_lib_tuple_like // >= C++23
2975 template<__tuple_like _TTuple, __tuple_like _UTuple,
2976 template<typename> class _TQual, template<typename> class _UQual,
2977 typename = make_index_sequence<tuple_size_v<_TTuple>>>
2978 struct __tuple_like_common_reference;
2980 template<__tuple_like _TTuple, __tuple_like _UTuple,
2981 template<typename> class _TQual, template<typename> class _UQual,
2984 { typename tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2985 _UQual<tuple_element_t<_Is, _UTuple>>>...>; }
2986 struct __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual, index_sequence<_Is...>>
2988 using type = tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2989 _UQual<tuple_element_t<_Is, _UTuple>>>...>;
2992 template<__tuple_like _TTuple, __tuple_like _UTuple,
2993 template<typename> class _TQual, template<typename> class _UQual>
2994 requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
2995 && is_same_v<_TTuple, decay_t<_TTuple>>
2996 && is_same_v<_UTuple, decay_t<_UTuple>>
2997 && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
2998 && requires { typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type; }
2999 struct basic_common_reference<_TTuple, _UTuple, _TQual, _UQual>
3001 using type = typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type;
3004 template<__tuple_like _TTuple, __tuple_like _UTuple,
3005 typename = make_index_sequence<tuple_size_v<_TTuple>>>
3006 struct __tuple_like_common_type;
3008 template<__tuple_like _TTuple, __tuple_like _UTuple, size_t... _Is>
3010 { typename tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3011 tuple_element_t<_Is, _UTuple>>...>; }
3012 struct __tuple_like_common_type<_TTuple, _UTuple, index_sequence<_Is...>>
3014 using type = tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3015 tuple_element_t<_Is, _UTuple>>...>;
3018 template<__tuple_like _TTuple, __tuple_like _UTuple>
3019 requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
3020 && is_same_v<_TTuple, decay_t<_TTuple>>
3021 && is_same_v<_UTuple, decay_t<_UTuple>>
3022 && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
3023 && requires { typename __tuple_like_common_type<_TTuple, _UTuple>::type; }
3024 struct common_type<_TTuple, _UTuple>
3026 using type = typename __tuple_like_common_type<_TTuple, _UTuple>::type;
3032#undef __glibcxx_no_dangling_refs
3034_GLIBCXX_END_NAMESPACE_VERSION
3039#endif // _GLIBCXX_TUPLE