libstdc++: Add missing std::tuple constructor [PR114147]
[official-gcc.git] / libstdc++-v3 / include / std / tuple
blob3065058e184dcd63aed5f5251269f94e288b3141
1 // <tuple> -*- C++ -*-
3 // Copyright (C) 2007-2024 Free Software Foundation, Inc.
4 //
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)
9 // any later version.
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.
27  */
29 #ifndef _GLIBCXX_TUPLE
30 #define _GLIBCXX_TUPLE 1
32 #pragma GCC system_header
34 #if __cplusplus < 201103L
35 # include <bits/c++0x_warning.h>
36 #else
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
43 # include <compare>
44 # include <bits/ranges_util.h>          // for std::ranges::subrange
45 #endif
47 #define __glibcxx_want_constexpr_tuple
48 #define __glibcxx_want_tuple_element_t
49 #define __glibcxx_want_tuples_by_type
50 #define __glibcxx_want_apply
51 #define __glibcxx_want_make_from_tuple
52 #define __glibcxx_want_ranges_zip
53 #define __glibcxx_want_tuple_like
54 #include <bits/version.h>
56 namespace std _GLIBCXX_VISIBILITY(default)
58 _GLIBCXX_BEGIN_NAMESPACE_VERSION
60   /**
61    *  @addtogroup utilities
62    *  @{
63    */
65   template<typename... _Elements>
66     class tuple;
68   template<typename _Tp>
69     struct __is_empty_non_tuple : is_empty<_Tp> { };
71   // Using EBO for elements that are tuples causes ambiguous base errors.
72   template<typename _El0, typename... _El>
73     struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { };
75   // Use the Empty Base-class Optimization for empty, non-final types.
76   template<typename _Tp>
77     using __empty_not_final
78     = __conditional_t<__is_final(_Tp), false_type,
79                       __is_empty_non_tuple<_Tp>>;
81   template<size_t _Idx, typename _Head,
82            bool = __empty_not_final<_Head>::value>
83     struct _Head_base;
85 #if __has_cpp_attribute(__no_unique_address__)
86   template<size_t _Idx, typename _Head>
87     struct _Head_base<_Idx, _Head, true>
88     {
89       constexpr _Head_base()
90       : _M_head_impl() { }
92       constexpr _Head_base(const _Head& __h)
93       : _M_head_impl(__h) { }
95       constexpr _Head_base(const _Head_base&) = default;
96       constexpr _Head_base(_Head_base&&) = default;
98       template<typename _UHead>
99         constexpr _Head_base(_UHead&& __h)
100         : _M_head_impl(std::forward<_UHead>(__h)) { }
102       _GLIBCXX20_CONSTEXPR
103       _Head_base(allocator_arg_t, __uses_alloc0)
104       : _M_head_impl() { }
106       template<typename _Alloc>
107         _GLIBCXX20_CONSTEXPR
108         _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
109         : _M_head_impl(allocator_arg, *__a._M_a) { }
111       template<typename _Alloc>
112         _GLIBCXX20_CONSTEXPR
113         _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
114         : _M_head_impl(*__a._M_a) { }
116       template<typename _UHead>
117         _GLIBCXX20_CONSTEXPR
118         _Head_base(__uses_alloc0, _UHead&& __uhead)
119         : _M_head_impl(std::forward<_UHead>(__uhead)) { }
121       template<typename _Alloc, typename _UHead>
122         _GLIBCXX20_CONSTEXPR
123         _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
124         : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
125         { }
127       template<typename _Alloc, typename _UHead>
128         _GLIBCXX20_CONSTEXPR
129         _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
130         : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
132       static constexpr _Head&
133       _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
135       static constexpr const _Head&
136       _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
138       [[__no_unique_address__]] _Head _M_head_impl;
139     };
140 #else
141   template<size_t _Idx, typename _Head>
142     struct _Head_base<_Idx, _Head, true>
143     : public _Head
144     {
145       constexpr _Head_base()
146       : _Head() { }
148       constexpr _Head_base(const _Head& __h)
149       : _Head(__h) { }
151       constexpr _Head_base(const _Head_base&) = default;
152       constexpr _Head_base(_Head_base&&) = default;
154       template<typename _UHead>
155         constexpr _Head_base(_UHead&& __h)
156         : _Head(std::forward<_UHead>(__h)) { }
158       _GLIBCXX20_CONSTEXPR
159       _Head_base(allocator_arg_t, __uses_alloc0)
160       : _Head() { }
162       template<typename _Alloc>
163         _GLIBCXX20_CONSTEXPR
164         _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
165         : _Head(allocator_arg, *__a._M_a) { }
167       template<typename _Alloc>
168         _GLIBCXX20_CONSTEXPR
169         _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
170         : _Head(*__a._M_a) { }
172       template<typename _UHead>
173         _GLIBCXX20_CONSTEXPR
174         _Head_base(__uses_alloc0, _UHead&& __uhead)
175         : _Head(std::forward<_UHead>(__uhead)) { }
177       template<typename _Alloc, typename _UHead>
178         _GLIBCXX20_CONSTEXPR
179         _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
180         : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
182       template<typename _Alloc, typename _UHead>
183         _GLIBCXX20_CONSTEXPR
184         _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
185         : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
187       static constexpr _Head&
188       _M_head(_Head_base& __b) noexcept { return __b; }
190       static constexpr const _Head&
191       _M_head(const _Head_base& __b) noexcept { return __b; }
192     };
193 #endif
195   template<size_t _Idx, typename _Head>
196     struct _Head_base<_Idx, _Head, false>
197     {
198       constexpr _Head_base()
199       : _M_head_impl() { }
201       constexpr _Head_base(const _Head& __h)
202       : _M_head_impl(__h) { }
204       constexpr _Head_base(const _Head_base&) = default;
205       constexpr _Head_base(_Head_base&&) = default;
207       template<typename _UHead>
208         constexpr _Head_base(_UHead&& __h)
209         : _M_head_impl(std::forward<_UHead>(__h)) { }
211       _GLIBCXX20_CONSTEXPR
212       _Head_base(allocator_arg_t, __uses_alloc0)
213       : _M_head_impl() { }
215       template<typename _Alloc>
216         _GLIBCXX20_CONSTEXPR
217         _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
218         : _M_head_impl(allocator_arg, *__a._M_a) { }
220       template<typename _Alloc>
221         _GLIBCXX20_CONSTEXPR
222         _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
223         : _M_head_impl(*__a._M_a) { }
225       template<typename _UHead>
226         _GLIBCXX20_CONSTEXPR
227         _Head_base(__uses_alloc0, _UHead&& __uhead)
228         : _M_head_impl(std::forward<_UHead>(__uhead)) { }
230       template<typename _Alloc, typename _UHead>
231         _GLIBCXX20_CONSTEXPR
232         _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
233         : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
234         { }
236       template<typename _Alloc, typename _UHead>
237         _GLIBCXX20_CONSTEXPR
238         _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
239         : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
241       static constexpr _Head&
242       _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
244       static constexpr const _Head&
245       _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
247       _Head _M_head_impl;
248     };
250 #if __cpp_lib_tuple_like // >= C++23
251   struct __tuple_like_tag_t { explicit __tuple_like_tag_t() = default; };
253   // These forward declarations are used by the operator<=> overload for
254   // tuple-like types.
255   template<typename _Cat, typename _Tp, typename _Up>
256     constexpr _Cat
257     __tuple_cmp(const _Tp&, const _Up&, index_sequence<>);
259   template<typename _Cat, typename _Tp, typename _Up,
260            size_t _Idx0, size_t... _Idxs>
261     constexpr _Cat
262     __tuple_cmp(const _Tp& __t, const _Up& __u,
263                 index_sequence<_Idx0, _Idxs...>);
264 #endif // C++23
266   /**
267    * Contains the actual implementation of the @c tuple template, stored
268    * as a recursive inheritance hierarchy from the first element (most
269    * derived class) to the last (least derived class). The @c Idx
270    * parameter gives the 0-based index of the element stored at this
271    * point in the hierarchy; we use it to implement a constant-time
272    * get() operation.
273    */
274   template<size_t _Idx, typename... _Elements>
275     struct _Tuple_impl;
277   /**
278    * Recursive tuple implementation. Here we store the @c Head element
279    * and derive from a @c Tuple_impl containing the remaining elements
280    * (which contains the @c Tail).
281    */
282   template<size_t _Idx, typename _Head, typename... _Tail>
283     struct _Tuple_impl<_Idx, _Head, _Tail...>
284     : public _Tuple_impl<_Idx + 1, _Tail...>,
285       private _Head_base<_Idx, _Head>
286     {
287       template<size_t, typename...> friend struct _Tuple_impl;
289       typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
290       typedef _Head_base<_Idx, _Head> _Base;
292       static constexpr _Head&
293       _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
295       static constexpr const _Head&
296       _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
298       static constexpr _Inherited&
299       _M_tail(_Tuple_impl& __t) noexcept { return __t; }
301       static constexpr const _Inherited&
302       _M_tail(const _Tuple_impl& __t) noexcept { return __t; }
304       constexpr _Tuple_impl()
305       : _Inherited(), _Base() { }
307       explicit constexpr
308       _Tuple_impl(const _Head& __head, const _Tail&... __tail)
309       : _Inherited(__tail...), _Base(__head)
310       { }
312       template<typename _UHead, typename... _UTail,
313                typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
314         explicit constexpr
315         _Tuple_impl(_UHead&& __head, _UTail&&... __tail)
316         : _Inherited(std::forward<_UTail>(__tail)...),
317           _Base(std::forward<_UHead>(__head))
318         { }
320       constexpr _Tuple_impl(const _Tuple_impl&) = default;
322       // _GLIBCXX_RESOLVE_LIB_DEFECTS
323       // 2729. Missing SFINAE on std::pair::operator=
324       _Tuple_impl& operator=(const _Tuple_impl&) = delete;
326       _Tuple_impl(_Tuple_impl&&) = default;
328       template<typename... _UElements>
329         constexpr
330         _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
331         : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
332           _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
333         { }
335       template<typename _UHead, typename... _UTails>
336         constexpr
337         _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
338         : _Inherited(std::move
339                      (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
340           _Base(std::forward<_UHead>
341                 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
342         { }
344 #if __cpp_lib_ranges_zip // >= C++23
345       template<typename... _UElements>
346         constexpr
347         _Tuple_impl(_Tuple_impl<_Idx, _UElements...>& __in)
348         : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
349           _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
350         { }
352       template<typename _UHead, typename... _UTails>
353         constexpr
354         _Tuple_impl(const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
355         : _Inherited(std::move
356                      (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
357           _Base(std::forward<const _UHead>
358                 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
359         { }
360 #endif // C++23
362 #if __cpp_lib_tuple_like // >= C++23
363       template<typename _UTuple, size_t... _Is>
364         constexpr
365         _Tuple_impl(__tuple_like_tag_t, _UTuple&& __u, index_sequence<_Is...>)
366         : _Tuple_impl(std::get<_Is>(std::forward<_UTuple>(__u))...)
367         { }
368 #endif // C++23
370       template<typename _Alloc>
371         _GLIBCXX20_CONSTEXPR
372         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
373         : _Inherited(__tag, __a),
374           _Base(__tag, __use_alloc<_Head>(__a))
375         { }
377       template<typename _Alloc>
378         _GLIBCXX20_CONSTEXPR
379         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
380                     const _Head& __head, const _Tail&... __tail)
381         : _Inherited(__tag, __a, __tail...),
382           _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head)
383         { }
385       template<typename _Alloc, typename _UHead, typename... _UTail,
386                typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
387         _GLIBCXX20_CONSTEXPR
388         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
389                     _UHead&& __head, _UTail&&... __tail)
390         : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
391           _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
392                 std::forward<_UHead>(__head))
393         { }
395       template<typename _Alloc>
396         _GLIBCXX20_CONSTEXPR
397         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
398                     const _Tuple_impl& __in)
399         : _Inherited(__tag, __a, _M_tail(__in)),
400           _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in))
401         { }
403       template<typename _Alloc>
404         _GLIBCXX20_CONSTEXPR
405         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
406                     _Tuple_impl&& __in)
407         : _Inherited(__tag, __a, std::move(_M_tail(__in))),
408           _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
409                 std::forward<_Head>(_M_head(__in)))
410         { }
412       template<typename _Alloc, typename _UHead, typename... _UTails>
413         _GLIBCXX20_CONSTEXPR
414         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
415                     const _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
416         : _Inherited(__tag, __a,
417                      _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
418           _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
419                 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
420         { }
422       template<typename _Alloc, typename _UHead, typename... _UTails>
423         _GLIBCXX20_CONSTEXPR
424         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
425                     _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
426         : _Inherited(__tag, __a, std::move
427                      (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
428           _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
429                 std::forward<_UHead>
430                 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
431         { }
433 #if __cpp_lib_ranges_zip // >= C++23
434       template<typename _Alloc, typename _UHead, typename... _UTails>
435         constexpr
436         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
437                     _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
438         : _Inherited(__tag, __a,
439                      _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
440           _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
441                 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
442         { }
444       template<typename _Alloc, typename _UHead, typename... _UTails>
445         constexpr
446         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
447                     const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
448         : _Inherited(__tag, __a, std::move
449                      (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
450           _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
451                 std::forward<const _UHead>
452                 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
453         { }
454 #endif // C++23
456 #if __cpp_lib_tuple_like // >= C++23
457       template<typename _Alloc, typename _UTuple, size_t... _Is>
458         constexpr
459         _Tuple_impl(__tuple_like_tag_t, allocator_arg_t __tag, const _Alloc& __a,
460                     _UTuple&& __u, index_sequence<_Is...>)
461         : _Tuple_impl(__tag, __a, std::get<_Is>(std::forward<_UTuple>(__u))...)
462         { }
463 #endif // C++23
465       template<typename... _UElements>
466         _GLIBCXX20_CONSTEXPR
467         void
468         _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in)
469         {
470           _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
471           _M_tail(*this)._M_assign(
472               _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
473         }
475       template<typename _UHead, typename... _UTails>
476         _GLIBCXX20_CONSTEXPR
477         void
478         _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
479         {
480           _M_head(*this) = std::forward<_UHead>
481             (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
482           _M_tail(*this)._M_assign(
483               std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
484         }
486 #if __cpp_lib_ranges_zip // >= C++23
487       template<typename... _UElements>
488         constexpr void
489         _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) const
490         {
491           _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
492           _M_tail(*this)._M_assign(
493               _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
494         }
496       template<typename _UHead, typename... _UTails>
497         constexpr void
498         _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) const
499         {
500           _M_head(*this) = std::forward<_UHead>
501             (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
502           _M_tail(*this)._M_assign(
503               std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
504         }
505 #endif // C++23
507 #if __cpp_lib_tuple_like // >= C++23
508       template<typename _UTuple>
509         constexpr void
510         _M_assign(__tuple_like_tag_t __tag, _UTuple&& __u)
511         {
512           _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u));
513           _M_tail(*this)._M_assign(__tag, std::forward<_UTuple>(__u));
514         }
516       template<typename _UTuple>
517         constexpr void
518         _M_assign(__tuple_like_tag_t __tag, _UTuple&& __u) const
519         {
520           _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u));
521           _M_tail(*this)._M_assign(__tag, std::forward<_UTuple>(__u));
522         }
523 #endif // C++23
525     protected:
526       _GLIBCXX20_CONSTEXPR
527       void
528       _M_swap(_Tuple_impl& __in)
529       {
530         using std::swap;
531         swap(_M_head(*this), _M_head(__in));
532         _Inherited::_M_swap(_M_tail(__in));
533       }
535 #if __cpp_lib_ranges_zip // >= C++23
536       constexpr void
537       _M_swap(const _Tuple_impl& __in) const
538       {
539         using std::swap;
540         swap(_M_head(*this), _M_head(__in));
541         _Inherited::_M_swap(_M_tail(__in));
542       }
543 #endif // C++23
544     };
546   // Basis case of inheritance recursion.
547   template<size_t _Idx, typename _Head>
548     struct _Tuple_impl<_Idx, _Head>
549     : private _Head_base<_Idx, _Head>
550     {
551       template<size_t, typename...> friend struct _Tuple_impl;
553       typedef _Head_base<_Idx, _Head> _Base;
555       static constexpr _Head&
556       _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
558       static constexpr const _Head&
559       _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
561       constexpr
562       _Tuple_impl()
563       : _Base() { }
565       explicit constexpr
566       _Tuple_impl(const _Head& __head)
567       : _Base(__head)
568       { }
570       template<typename _UHead>
571         explicit constexpr
572         _Tuple_impl(_UHead&& __head)
573         : _Base(std::forward<_UHead>(__head))
574         { }
576       constexpr _Tuple_impl(const _Tuple_impl&) = default;
578       // _GLIBCXX_RESOLVE_LIB_DEFECTS
579       // 2729. Missing SFINAE on std::pair::operator=
580       _Tuple_impl& operator=(const _Tuple_impl&) = delete;
582 #if _GLIBCXX_INLINE_VERSION
583       _Tuple_impl(_Tuple_impl&&) = default;
584 #else
585       constexpr
586       _Tuple_impl(_Tuple_impl&& __in)
587       noexcept(is_nothrow_move_constructible<_Head>::value)
588       : _Base(static_cast<_Base&&>(__in))
589       { }
590 #endif
592       template<typename _UHead>
593         constexpr
594         _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in)
595         : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
596         { }
598       template<typename _UHead>
599         constexpr
600         _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in)
601         : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
602         { }
604 #if __cpp_lib_ranges_zip // >= C++23
605       template<typename _UHead>
606         constexpr
607         _Tuple_impl(_Tuple_impl<_Idx, _UHead>& __in)
608         : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
609         { }
611       template<typename _UHead>
612         constexpr
613         _Tuple_impl(const _Tuple_impl<_Idx, _UHead>&& __in)
614         : _Base(std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
615         { }
616 #endif // C++23
618 #if __cpp_lib_tuple_like // >= C++23
619       template<typename _UTuple>
620         constexpr
621         _Tuple_impl(__tuple_like_tag_t, _UTuple&& __u, index_sequence<0>)
622         : _Tuple_impl(std::get<0>(std::forward<_UTuple>(__u)))
623         { }
624 #endif // C++23
626       template<typename _Alloc>
627         _GLIBCXX20_CONSTEXPR
628         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
629         : _Base(__tag, __use_alloc<_Head>(__a))
630         { }
632       template<typename _Alloc>
633         _GLIBCXX20_CONSTEXPR
634         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
635                     const _Head& __head)
636         : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), __head)
637         { }
639       template<typename _Alloc, typename _UHead>
640         _GLIBCXX20_CONSTEXPR
641         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
642                     _UHead&& __head)
643         : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
644                 std::forward<_UHead>(__head))
645         { }
647       template<typename _Alloc>
648         _GLIBCXX20_CONSTEXPR
649         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
650                     const _Tuple_impl& __in)
651         : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), _M_head(__in))
652         { }
654       template<typename _Alloc>
655         _GLIBCXX20_CONSTEXPR
656         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
657                     _Tuple_impl&& __in)
658         : _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
659                 std::forward<_Head>(_M_head(__in)))
660         { }
662       template<typename _Alloc, typename _UHead>
663         _GLIBCXX20_CONSTEXPR
664         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
665                     const _Tuple_impl<_Idx, _UHead>& __in)
666         : _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
667                 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
668         { }
670       template<typename _Alloc, typename _UHead>
671         _GLIBCXX20_CONSTEXPR
672         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
673                     _Tuple_impl<_Idx, _UHead>&& __in)
674         : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
675                 std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
676         { }
678 #if __cpp_lib_ranges_zip // >= C++23
679       template<typename _Alloc, typename _UHead>
680         constexpr
681         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
682                     _Tuple_impl<_Idx, _UHead>& __in)
683         : _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
684                 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
685         { }
687       template<typename _Alloc, typename _UHead>
688         constexpr
689         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
690                     const _Tuple_impl<_Idx, _UHead>&& __in)
691         : _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
692                 std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
693         { }
694 #endif // C++23
696 #if __cpp_lib_tuple_like // >= C++23
697       template<typename _Alloc, typename _UTuple>
698         constexpr
699         _Tuple_impl(__tuple_like_tag_t, allocator_arg_t __tag, const _Alloc& __a,
700                     _UTuple&& __u, index_sequence<0>)
701         : _Tuple_impl(__tag, __a, std::get<0>(std::forward<_UTuple>(__u)))
702         { }
703 #endif // C++23
705       template<typename _UHead>
706         _GLIBCXX20_CONSTEXPR
707         void
708         _M_assign(const _Tuple_impl<_Idx, _UHead>& __in)
709         {
710           _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
711         }
713       template<typename _UHead>
714         _GLIBCXX20_CONSTEXPR
715         void
716         _M_assign(_Tuple_impl<_Idx, _UHead>&& __in)
717         {
718           _M_head(*this)
719             = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
720         }
722 #if __cpp_lib_ranges_zip // >= C++23
723       template<typename _UHead>
724         constexpr void
725         _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) const
726         {
727           _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
728         }
730       template<typename _UHead>
731         constexpr void
732         _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) const
733         {
734           _M_head(*this)
735             = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
736         }
737 #endif // C++23
739 #if __cpp_lib_tuple_like // >= C++23
740     template<typename _UTuple>
741       constexpr void
742       _M_assign(__tuple_like_tag_t, _UTuple&& __u)
743       { _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); }
745     template<typename _UTuple>
746       constexpr void
747       _M_assign(__tuple_like_tag_t, _UTuple&& __u) const
748       { _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); }
749 #endif // C++23
751     protected:
752       _GLIBCXX20_CONSTEXPR
753       void
754       _M_swap(_Tuple_impl& __in)
755       {
756         using std::swap;
757         swap(_M_head(*this), _M_head(__in));
758       }
760 #if __cpp_lib_ranges_zip // >= C++23
761       constexpr void
762       _M_swap(const _Tuple_impl& __in) const
763       {
764         using std::swap;
765         swap(_M_head(*this), _M_head(__in));
766       }
767 #endif // C++23
768     };
770   // Concept utility functions, reused in conditionally-explicit
771   // constructors.
772   template<bool, typename... _Types>
773     struct _TupleConstraints
774     {
775       template<typename... _UTypes>
776         using __constructible = __and_<is_constructible<_Types, _UTypes>...>;
778       template<typename... _UTypes>
779         using __convertible = __and_<is_convertible<_UTypes, _Types>...>;
781       // Constraint for a non-explicit constructor.
782       // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
783       // and every Ui is implicitly convertible to Ti.
784       template<typename... _UTypes>
785         static constexpr bool __is_implicitly_constructible()
786         {
787           return __and_<__constructible<_UTypes...>,
788                         __convertible<_UTypes...>
789                         >::value;
790         }
792       // Constraint for a non-explicit constructor.
793       // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
794       // but not every Ui is implicitly convertible to Ti.
795       template<typename... _UTypes>
796         static constexpr bool __is_explicitly_constructible()
797         {
798           return __and_<__constructible<_UTypes...>,
799                         __not_<__convertible<_UTypes...>>
800                         >::value;
801         }
803       static constexpr bool __is_implicitly_default_constructible()
804       {
805         return __and_<std::__is_implicitly_default_constructible<_Types>...
806                       >::value;
807       }
809       static constexpr bool __is_explicitly_default_constructible()
810       {
811         return __and_<is_default_constructible<_Types>...,
812                       __not_<__and_<
813                         std::__is_implicitly_default_constructible<_Types>...>
814                       >>::value;
815       }
816     };
818   // Partial specialization used when a required precondition isn't met,
819   // e.g. when sizeof...(_Types) != sizeof...(_UTypes).
820   template<typename... _Types>
821     struct _TupleConstraints<false, _Types...>
822     {
823       template<typename... _UTypes>
824         static constexpr bool __is_implicitly_constructible()
825         { return false; }
827       template<typename... _UTypes>
828         static constexpr bool __is_explicitly_constructible()
829         { return false; }
830     };
832   /// Primary class template, tuple
833   template<typename... _Elements>
834     class tuple : public _Tuple_impl<0, _Elements...>
835     {
836       using _Inherited = _Tuple_impl<0, _Elements...>;
838 #if __cpp_concepts && __cpp_consteval && __cpp_conditional_explicit // >= C++20
839       template<typename... _UTypes>
840         static consteval bool
841         __constructible()
842         {
843           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
844             return __and_v<is_constructible<_Elements, _UTypes>...>;
845           else
846             return false;
847         }
849       template<typename... _UTypes>
850         static consteval bool
851         __nothrow_constructible()
852         {
853           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
854             return __and_v<is_nothrow_constructible<_Elements, _UTypes>...>;
855           else
856             return false;
857         }
859       template<typename... _UTypes>
860         static consteval bool
861         __convertible()
862         {
863           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
864             return __and_v<is_convertible<_UTypes, _Elements>...>;
865           else
866             return false;
867         }
869       // _GLIBCXX_RESOLVE_LIB_DEFECTS
870       // 3121. tuple constructor constraints for UTypes&&... overloads
871       template<typename... _UTypes>
872         static consteval bool
873         __disambiguating_constraint()
874         {
875           if constexpr (sizeof...(_Elements) != sizeof...(_UTypes))
876             return false;
877           else if constexpr (sizeof...(_Elements) == 1)
878             {
879               using _U0 = typename _Nth_type<0, _UTypes...>::type;
880               return !is_same_v<remove_cvref_t<_U0>, tuple>;
881             }
882           else if constexpr (sizeof...(_Elements) < 4)
883             {
884               using _U0 = typename _Nth_type<0, _UTypes...>::type;
885               if constexpr (!is_same_v<remove_cvref_t<_U0>, allocator_arg_t>)
886                 return true;
887               else
888                 {
889                   using _T0 = typename _Nth_type<0, _Elements...>::type;
890                   return is_same_v<remove_cvref_t<_T0>, allocator_arg_t>;
891                 }
892             }
893           return true;
894         }
896       // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
897       // and the single element in Types can be initialized from TUPLE,
898       // or is the same type as tuple_element_t<0, TUPLE>.
899       template<typename _Tuple>
900         static consteval bool
901         __use_other_ctor()
902         {
903           if constexpr (sizeof...(_Elements) != 1)
904             return false;
905           else if constexpr (is_same_v<remove_cvref_t<_Tuple>, tuple>)
906             return true; // Should use a copy/move constructor instead.
907           else
908             {
909               using _Tp = typename _Nth_type<0, _Elements...>::type;
910               if constexpr (is_convertible_v<_Tuple, _Tp>)
911                 return true;
912               else if constexpr (is_constructible_v<_Tp, _Tuple>)
913                 return true;
914             }
915           return false;
916         }
918       template<typename... _Up>
919         static consteval bool
920         __dangles()
921         {
922 #if __has_builtin(__reference_constructs_from_temporary)
923           return (__reference_constructs_from_temporary(_Elements, _Up&&)
924                     || ...);
925 #else
926           return false;
927 #endif
928         }
930 #if __cpp_lib_tuple_like // >= C++23
931       // _GLIBCXX_RESOLVE_LIB_DEFECTS
932       // 4045. tuple can create dangling references from tuple-like
933       template<typename _UTuple>
934         static consteval bool
935         __dangles_from_tuple_like()
936         {
937           return []<size_t... _Is>(index_sequence<_Is...>) {
938             return __dangles<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
939           }(index_sequence_for<_Elements...>{});
940         }
942       template<typename _UTuple>
943         static consteval bool
944         __constructible_from_tuple_like()
945         {
946           return []<size_t... _Is>(index_sequence<_Is...>) {
947             return __constructible<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
948           }(index_sequence_for<_Elements...>{});
949         }
951       template<typename _UTuple>
952         static consteval bool
953         __convertible_from_tuple_like()
954         {
955           return []<size_t... _Is>(index_sequence<_Is...>) {
956             return __convertible<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
957           }(index_sequence_for<_Elements...>{});
958         }
959 #endif // C++23
961     public:
962       constexpr
963       explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
964       tuple()
965       noexcept((is_nothrow_default_constructible_v<_Elements> && ...))
966       requires (is_default_constructible_v<_Elements> && ...)
967       : _Inherited()
968       { }
970       constexpr explicit(!__convertible<const _Elements&...>())
971       tuple(const _Elements&... __elements)
972       noexcept(__nothrow_constructible<const _Elements&...>())
973       requires (__constructible<const _Elements&...>())
974       : _Inherited(__elements...)
975       { }
977       template<typename... _UTypes>
978         requires (__disambiguating_constraint<_UTypes...>())
979           && (__constructible<_UTypes...>())
980           && (!__dangles<_UTypes...>())
981         constexpr explicit(!__convertible<_UTypes...>())
982         tuple(_UTypes&&... __u)
983         noexcept(__nothrow_constructible<_UTypes...>())
984         : _Inherited(std::forward<_UTypes>(__u)...)
985         { }
987       template<typename... _UTypes>
988         requires (__disambiguating_constraint<_UTypes...>())
989           && (__constructible<_UTypes...>())
990           && (__dangles<_UTypes...>())
991         tuple(_UTypes&&...) = delete;
993       constexpr tuple(const tuple&) = default;
995       constexpr tuple(tuple&&) = default;
997       template<typename... _UTypes>
998         requires (__constructible<const _UTypes&...>())
999           && (!__use_other_ctor<const tuple<_UTypes...>&>())
1000           && (!__dangles<const _UTypes&...>())
1001         constexpr explicit(!__convertible<const _UTypes&...>())
1002         tuple(const tuple<_UTypes...>& __u)
1003         noexcept(__nothrow_constructible<const _UTypes&...>())
1004         : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1005         { }
1007       template<typename... _UTypes>
1008         requires (__constructible<const _UTypes&...>())
1009           && (!__use_other_ctor<const tuple<_UTypes...>&>())
1010           && (__dangles<const _UTypes&...>())
1011         tuple(const tuple<_UTypes...>&) = delete;
1013       template<typename... _UTypes>
1014         requires (__constructible<_UTypes...>())
1015           && (!__use_other_ctor<tuple<_UTypes...>>())
1016           && (!__dangles<_UTypes...>())
1017         constexpr explicit(!__convertible<_UTypes...>())
1018         tuple(tuple<_UTypes...>&& __u)
1019         noexcept(__nothrow_constructible<_UTypes...>())
1020         : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1021         { }
1023       template<typename... _UTypes>
1024         requires (__constructible<_UTypes...>())
1025           && (!__use_other_ctor<tuple<_UTypes...>>())
1026           && (__dangles<_UTypes...>())
1027         tuple(tuple<_UTypes...>&&) = delete;
1029 #if __cpp_lib_ranges_zip // >= C++23
1030       template<typename... _UTypes>
1031         requires (__constructible<_UTypes&...>())
1032           && (!__use_other_ctor<tuple<_UTypes...>&>())
1033           && (!__dangles<_UTypes&...>())
1034         constexpr explicit(!__convertible<_UTypes&...>())
1035         tuple(tuple<_UTypes...>& __u)
1036         noexcept(__nothrow_constructible<_UTypes&...>())
1037         : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1038         { }
1040       template<typename... _UTypes>
1041         requires (__constructible<_UTypes&...>())
1042           && (!__use_other_ctor<tuple<_UTypes...>&>())
1043           && (__dangles<_UTypes&...>())
1044         tuple(tuple<_UTypes...>&) = delete;
1046       template<typename... _UTypes>
1047         requires (__constructible<const _UTypes...>())
1048           && (!__use_other_ctor<const tuple<_UTypes...>>())
1049           && (!__dangles<const _UTypes...>())
1050         constexpr explicit(!__convertible<const _UTypes...>())
1051         tuple(const tuple<_UTypes...>&& __u)
1052         noexcept(__nothrow_constructible<const _UTypes...>())
1053         : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1054         { }
1056       template<typename... _UTypes>
1057         requires (__constructible<const _UTypes...>())
1058           && (!__use_other_ctor<const tuple<_UTypes...>>())
1059           && (__dangles<const _UTypes...>())
1060         tuple(const tuple<_UTypes...>&&) = delete;
1061 #endif // C++23
1063       template<typename _U1, typename _U2>
1064         requires (sizeof...(_Elements) == 2)
1065           && (__constructible<const _U1&, const _U2&>())
1066           && (!__dangles<const _U1&, const _U2&>())
1067         constexpr explicit(!__convertible<const _U1&, const _U2&>())
1068         tuple(const pair<_U1, _U2>& __u)
1069         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1070         : _Inherited(__u.first, __u.second)
1071         { }
1073       template<typename _U1, typename _U2>
1074         requires (sizeof...(_Elements) == 2)
1075           && (__constructible<const _U1&, const _U2&>())
1076           && (__dangles<const _U1&, const _U2&>())
1077         tuple(const pair<_U1, _U2>&) = delete;
1079       template<typename _U1, typename _U2>
1080         requires (sizeof...(_Elements) == 2)
1081           && (__constructible<_U1, _U2>())
1082           && (!__dangles<_U1, _U2>())
1083         constexpr explicit(!__convertible<_U1, _U2>())
1084         tuple(pair<_U1, _U2>&& __u)
1085         noexcept(__nothrow_constructible<_U1, _U2>())
1086         : _Inherited(std::forward<_U1>(__u.first),
1087                      std::forward<_U2>(__u.second))
1088         { }
1090       template<typename _U1, typename _U2>
1091         requires (sizeof...(_Elements) == 2)
1092           && (__constructible<_U1, _U2>())
1093           && (__dangles<_U1, _U2>())
1094         tuple(pair<_U1, _U2>&&) = delete;
1096 #if __cpp_lib_ranges_zip // >= C++23
1097       template<typename _U1, typename _U2>
1098         requires (sizeof...(_Elements) == 2)
1099           && (__constructible<_U1&, _U2&>())
1100           && (!__dangles<_U1&, _U2&>())
1101         constexpr explicit(!__convertible<_U1&, _U2&>())
1102         tuple(pair<_U1, _U2>& __u)
1103         noexcept(__nothrow_constructible<_U1&, _U2&>())
1104         : _Inherited(__u.first, __u.second)
1105         { }
1107       template<typename _U1, typename _U2>
1108         requires (sizeof...(_Elements) == 2)
1109           && (__constructible<_U1&, _U2&>())
1110           && (__dangles<_U1&, _U2&>())
1111         tuple(pair<_U1, _U2>&) = delete;
1113       template<typename _U1, typename _U2>
1114         requires (sizeof...(_Elements) == 2)
1115           && (__constructible<const _U1, const _U2>())
1116           && (!__dangles<const _U1, const _U2>())
1117         constexpr explicit(!__convertible<const _U1, const _U2>())
1118         tuple(const pair<_U1, _U2>&& __u)
1119         noexcept(__nothrow_constructible<const _U1, const _U2>())
1120         : _Inherited(std::forward<const _U1>(__u.first),
1121                      std::forward<const _U2>(__u.second))
1122         { }
1124       template<typename _U1, typename _U2>
1125         requires (sizeof...(_Elements) == 2)
1126           && (__constructible<const _U1, const _U2>())
1127           && (__dangles<const _U1, const _U2>())
1128         tuple(const pair<_U1, _U2>&&) = delete;
1129 #endif // C++23
1131 #if __cpp_lib_tuple_like // >= C++23
1132       template<__eligible_tuple_like<tuple> _UTuple>
1133         requires (__constructible_from_tuple_like<_UTuple>())
1134           && (!__use_other_ctor<_UTuple>())
1135           && (!__dangles_from_tuple_like<_UTuple>())
1136         constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
1137         tuple(_UTuple&& __u)
1138         : _Inherited(__tuple_like_tag_t{},
1139                      std::forward<_UTuple>(__u),
1140                      index_sequence_for<_Elements...>{})
1141         { }
1143       template<__eligible_tuple_like<tuple> _UTuple>
1144         requires (__constructible_from_tuple_like<_UTuple>())
1145           && (!__use_other_ctor<_UTuple>())
1146           && (__dangles_from_tuple_like<_UTuple>())
1147         tuple(_UTuple&&) = delete;
1148 #endif // C++23
1150       // Allocator-extended constructors.
1152       template<typename _Alloc>
1153         constexpr
1154         explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
1155         tuple(allocator_arg_t __tag, const _Alloc& __a)
1156         requires (is_default_constructible_v<_Elements> && ...)
1157         : _Inherited(__tag, __a)
1158         { }
1160       template<typename _Alloc>
1161         constexpr explicit(!__convertible<const _Elements&...>())
1162         tuple(allocator_arg_t __tag, const _Alloc& __a,
1163               const _Elements&... __elements)
1164         requires (__constructible<const _Elements&...>())
1165         : _Inherited(__tag, __a, __elements...)
1166         { }
1168       template<typename _Alloc, typename... _UTypes>
1169         requires (__disambiguating_constraint<_UTypes...>())
1170           && (__constructible<_UTypes...>())
1171           && (!__dangles<_UTypes...>())
1172         constexpr explicit(!__convertible<_UTypes...>())
1173         tuple(allocator_arg_t __tag, const _Alloc& __a, _UTypes&&... __u)
1174         : _Inherited(__tag, __a, std::forward<_UTypes>(__u)...)
1175         { }
1177       template<typename _Alloc, typename... _UTypes>
1178         requires (__disambiguating_constraint<_UTypes...>())
1179           && (__constructible<_UTypes...>())
1180           && (__dangles<_UTypes...>())
1181         tuple(allocator_arg_t, const _Alloc&, _UTypes&&...) = delete;
1183       template<typename _Alloc>
1184         constexpr
1185         tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __u)
1186         : _Inherited(__tag, __a, static_cast<const _Inherited&>(__u))
1187         { }
1189       template<typename _Alloc>
1190         requires (__constructible<_Elements...>())
1191         constexpr
1192         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __u)
1193         : _Inherited(__tag, __a, static_cast<_Inherited&&>(__u))
1194         { }
1196       template<typename _Alloc, typename... _UTypes>
1197         requires (__constructible<const _UTypes&...>())
1198           && (!__use_other_ctor<const tuple<_UTypes...>&>())
1199           && (!__dangles<const _UTypes&...>())
1200         constexpr explicit(!__convertible<const _UTypes&...>())
1201         tuple(allocator_arg_t __tag, const _Alloc& __a,
1202               const tuple<_UTypes...>& __u)
1203         : _Inherited(__tag, __a,
1204                      static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1205         { }
1207       template<typename _Alloc, typename... _UTypes>
1208         requires (__constructible<const _UTypes&...>())
1209           && (!__use_other_ctor<const tuple<_UTypes...>&>())
1210           && (__dangles<const _UTypes&...>())
1211         tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&) = delete;
1213       template<typename _Alloc, typename... _UTypes>
1214         requires (__constructible<_UTypes...>())
1215           && (!__use_other_ctor<tuple<_UTypes...>>())
1216           && (!__dangles<_UTypes...>())
1217         constexpr explicit(!__use_other_ctor<tuple<_UTypes...>>())
1218         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>&& __u)
1219         : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1220         { }
1222       template<typename _Alloc, typename... _UTypes>
1223         requires (__constructible<_UTypes...>())
1224           && (!__use_other_ctor<tuple<_UTypes...>>())
1225           && (__dangles<_UTypes...>())
1226         tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&&) = delete;
1228 #if __cpp_lib_ranges_zip // >= C++23
1229       template<typename _Alloc, typename... _UTypes>
1230         requires (__constructible<_UTypes&...>())
1231           && (!__use_other_ctor<tuple<_UTypes...>&>())
1232           && (!__dangles<_UTypes&...>())
1233         constexpr explicit(!__convertible<_UTypes&...>())
1234         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>& __u)
1235         : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1236         { }
1238       template<typename _Alloc, typename... _UTypes>
1239         requires (__constructible<_UTypes&...>())
1240           && (!__use_other_ctor<tuple<_UTypes...>&>())
1241           && (__dangles<_UTypes&...>())
1242         tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&) = delete;
1244       template<typename _Alloc, typename... _UTypes>
1245         requires (__constructible<const _UTypes...>())
1246           && (!__use_other_ctor<const tuple<_UTypes...>>())
1247           && (!__dangles<const _UTypes...>())
1248         constexpr explicit(!__convertible<const _UTypes...>())
1249         tuple(allocator_arg_t __tag, const _Alloc& __a,
1250               const tuple<_UTypes...>&& __u)
1251         : _Inherited(__tag, __a,
1252                      static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1253         { }
1255       template<typename _Alloc, typename... _UTypes>
1256         requires (__constructible<const _UTypes...>())
1257           && (!__use_other_ctor<const tuple<_UTypes...>>())
1258           && (__dangles<const _UTypes...>())
1259         tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&&) = delete;
1260 #endif // C++23
1262       template<typename _Alloc, typename _U1, typename _U2>
1263         requires (sizeof...(_Elements) == 2)
1264           && (__constructible<const _U1&, const _U2&>())
1265           && (!__dangles<const _U1&, const _U2&>())
1266         constexpr explicit(!__convertible<const _U1&, const _U2&>())
1267         tuple(allocator_arg_t __tag, const _Alloc& __a,
1268               const pair<_U1, _U2>& __u)
1269         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1270         : _Inherited(__tag, __a, __u.first, __u.second)
1271         { }
1273       template<typename _Alloc, typename _U1, typename _U2>
1274         requires (sizeof...(_Elements) == 2)
1275           && (__constructible<const _U1&, const _U2&>())
1276           && (__dangles<const _U1&, const _U2&>())
1277         tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&) = delete;
1279       template<typename _Alloc, typename _U1, typename _U2>
1280         requires (sizeof...(_Elements) == 2)
1281           && (__constructible<_U1, _U2>())
1282           && (!__dangles<_U1, _U2>())
1283         constexpr explicit(!__convertible<_U1, _U2>())
1284         tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __u)
1285         noexcept(__nothrow_constructible<_U1, _U2>())
1286         : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1287         { }
1289       template<typename _Alloc, typename _U1, typename _U2>
1290         requires (sizeof...(_Elements) == 2)
1291           && (__constructible<_U1, _U2>())
1292           && (__dangles<_U1, _U2>())
1293         tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&) = delete;
1295 #if __cpp_lib_ranges_zip // >= C++23
1296       template<typename _Alloc, typename _U1, typename _U2>
1297         requires (sizeof...(_Elements) == 2)
1298           && (__constructible<_U1&, _U2&>())
1299           && (!__dangles<_U1&, _U2&>())
1300         constexpr explicit(!__convertible<_U1&, _U2&>())
1301         tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>& __u)
1302         noexcept(__nothrow_constructible<_U1&, _U2&>())
1303         : _Inherited(__tag, __a, __u.first, __u.second)
1304         { }
1306       template<typename _Alloc, typename _U1, typename _U2>
1307         requires (sizeof...(_Elements) == 2)
1308           && (__constructible<_U1&, _U2&>())
1309           && (__dangles<_U1&, _U2&>())
1310         tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&) = delete;
1312       template<typename _Alloc, typename _U1, typename _U2>
1313         requires (sizeof...(_Elements) == 2)
1314           && (__constructible<const _U1, const _U2>())
1315           && (!__dangles<const _U1, const _U2>())
1316         constexpr explicit(!__convertible<const _U1, const _U2>())
1317         tuple(allocator_arg_t __tag, const _Alloc& __a,
1318         const pair<_U1, _U2>&& __u)
1319         noexcept(__nothrow_constructible<const _U1, const _U2>())
1320         : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1321         { }
1323       template<typename _Alloc, typename _U1, typename _U2>
1324         requires (sizeof...(_Elements) == 2)
1325           && (__constructible<const _U1, const _U2>())
1326           && (__dangles<const _U1, const _U2>())
1327         tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&&) = delete;
1328 #endif // C++23
1330 #if __cpp_lib_tuple_like // >= C++23
1331       template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
1332         requires (__constructible_from_tuple_like<_UTuple>())
1333           && (!__use_other_ctor<_UTuple>())
1334           && (!__dangles_from_tuple_like<_UTuple>())
1335         constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
1336         tuple(allocator_arg_t __tag, const _Alloc& __a, _UTuple&& __u)
1337         : _Inherited(__tuple_like_tag_t{},
1338                      __tag, __a, std::forward<_UTuple>(__u),
1339                      index_sequence_for<_Elements...>{})
1340         { }
1342       template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
1343         requires (__constructible_from_tuple_like<_UTuple>())
1344           && (!__use_other_ctor<_UTuple>())
1345           && (__dangles_from_tuple_like<_UTuple>())
1346         tuple(allocator_arg_t, const _Alloc&, _UTuple&&) = delete;
1347 #endif // C++23
1349 #else // !(concepts && conditional_explicit)
1351       template<bool _Cond>
1352         using _TCC = _TupleConstraints<_Cond, _Elements...>;
1354       // Constraint for non-explicit default constructor
1355       template<bool _Dummy>
1356         using _ImplicitDefaultCtor = __enable_if_t<
1357           _TCC<_Dummy>::__is_implicitly_default_constructible(),
1358           bool>;
1360       // Constraint for explicit default constructor
1361       template<bool _Dummy>
1362         using _ExplicitDefaultCtor = __enable_if_t<
1363           _TCC<_Dummy>::__is_explicitly_default_constructible(),
1364           bool>;
1366       // Constraint for non-explicit constructors
1367       template<bool _Cond, typename... _Args>
1368         using _ImplicitCtor = __enable_if_t<
1369           _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
1370           bool>;
1372       // Constraint for non-explicit constructors
1373       template<bool _Cond, typename... _Args>
1374         using _ExplicitCtor = __enable_if_t<
1375           _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
1376           bool>;
1378       // Condition for noexcept-specifier of a constructor.
1379       template<typename... _UElements>
1380         static constexpr bool __nothrow_constructible()
1381         {
1382           return
1383             __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
1384         }
1386       // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1.
1387       template<typename _Up>
1388         static constexpr bool __valid_args()
1389         {
1390           return sizeof...(_Elements) == 1
1391             && !is_same<tuple, __remove_cvref_t<_Up>>::value;
1392         }
1394       // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1.
1395       template<typename, typename, typename... _Tail>
1396         static constexpr bool __valid_args()
1397         { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); }
1399       /* Constraint for constructors with a tuple<UTypes...> parameter ensures
1400        * that the constructor is only viable when it would not interfere with
1401        * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&).
1402        * Such constructors are only viable if:
1403        * either sizeof...(Types) != 1,
1404        * or (when Types... expands to T and UTypes... expands to U)
1405        * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>,
1406        * and is_same_v<T, U> are all false.
1407        */
1408       template<typename _Tuple, typename = tuple,
1409                typename = __remove_cvref_t<_Tuple>>
1410         struct _UseOtherCtor
1411         : false_type
1412         { };
1413       // If TUPLE is convertible to the single element in *this,
1414       // then TUPLE should match tuple(UTypes&&...) instead.
1415       template<typename _Tuple, typename _Tp, typename _Up>
1416         struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>>
1417         : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>::type
1418         { };
1419       // If TUPLE and *this each have a single element of the same type,
1420       // then TUPLE should match a copy/move constructor instead.
1421       template<typename _Tuple, typename _Tp>
1422         struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>>
1423         : true_type
1424         { };
1426       // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
1427       // and the single element in Types can be initialized from TUPLE,
1428       // or is the same type as tuple_element_t<0, TUPLE>.
1429       template<typename _Tuple>
1430         static constexpr bool __use_other_ctor()
1431         { return _UseOtherCtor<_Tuple>::value; }
1433       /// @cond undocumented
1434 #undef __glibcxx_no_dangling_refs
1435 #if __has_builtin(__reference_constructs_from_temporary) \
1436       && defined _GLIBCXX_DEBUG
1437       // Error if construction from U... would create a dangling ref.
1438 # if __cpp_fold_expressions
1439 #  define __glibcxx_dangling_refs(U) \
1440   (__reference_constructs_from_temporary(_Elements, U) || ...)
1441 # else
1442 #  define __glibcxx_dangling_refs(U) \
1443   __or_<__bool_constant<__reference_constructs_from_temporary(_Elements, U) \
1444        >...>::value
1445 # endif
1446 # define __glibcxx_no_dangling_refs(U) \
1447   static_assert(!__glibcxx_dangling_refs(U), \
1448                 "std::tuple constructor creates a dangling reference")
1449 #else
1450 # define __glibcxx_no_dangling_refs(U)
1451 #endif
1452       /// @endcond
1454     public:
1455       template<typename _Dummy = void,
1456                _ImplicitDefaultCtor<is_void<_Dummy>::value> = true>
1457         constexpr
1458         tuple()
1459         noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1460         : _Inherited() { }
1462       template<typename _Dummy = void,
1463                _ExplicitDefaultCtor<is_void<_Dummy>::value> = false>
1464         explicit constexpr
1465         tuple()
1466         noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1467         : _Inherited() { }
1469       template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1470                _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1471         constexpr
1472         tuple(const _Elements&... __elements)
1473         noexcept(__nothrow_constructible<const _Elements&...>())
1474         : _Inherited(__elements...) { }
1476       template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1477                _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1478         explicit constexpr
1479         tuple(const _Elements&... __elements)
1480         noexcept(__nothrow_constructible<const _Elements&...>())
1481         : _Inherited(__elements...) { }
1483       template<typename... _UElements,
1484                bool _Valid = __valid_args<_UElements...>(),
1485                _ImplicitCtor<_Valid, _UElements...> = true>
1486         constexpr
1487         tuple(_UElements&&... __elements)
1488         noexcept(__nothrow_constructible<_UElements...>())
1489         : _Inherited(std::forward<_UElements>(__elements)...)
1490         { __glibcxx_no_dangling_refs(_UElements&&); }
1492       template<typename... _UElements,
1493                bool _Valid = __valid_args<_UElements...>(),
1494                _ExplicitCtor<_Valid, _UElements...> = false>
1495         explicit constexpr
1496         tuple(_UElements&&... __elements)
1497         noexcept(__nothrow_constructible<_UElements...>())
1498         : _Inherited(std::forward<_UElements>(__elements)...)
1499         { __glibcxx_no_dangling_refs(_UElements&&); }
1501       constexpr tuple(const tuple&) = default;
1503       constexpr tuple(tuple&&) = default;
1505       template<typename... _UElements,
1506                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1507                            && !__use_other_ctor<const tuple<_UElements...>&>(),
1508                _ImplicitCtor<_Valid, const _UElements&...> = true>
1509         constexpr
1510         tuple(const tuple<_UElements...>& __in)
1511         noexcept(__nothrow_constructible<const _UElements&...>())
1512         : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1513         { __glibcxx_no_dangling_refs(const _UElements&); }
1515       template<typename... _UElements,
1516                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1517                            && !__use_other_ctor<const tuple<_UElements...>&>(),
1518                _ExplicitCtor<_Valid, const _UElements&...> = false>
1519         explicit constexpr
1520         tuple(const tuple<_UElements...>& __in)
1521         noexcept(__nothrow_constructible<const _UElements&...>())
1522         : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1523         { __glibcxx_no_dangling_refs(const _UElements&); }
1525       template<typename... _UElements,
1526                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1527                              && !__use_other_ctor<tuple<_UElements...>&&>(),
1528                _ImplicitCtor<_Valid, _UElements...> = true>
1529         constexpr
1530         tuple(tuple<_UElements...>&& __in)
1531         noexcept(__nothrow_constructible<_UElements...>())
1532         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1533         { __glibcxx_no_dangling_refs(_UElements&&); }
1535       template<typename... _UElements,
1536                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1537                              && !__use_other_ctor<tuple<_UElements...>&&>(),
1538                _ExplicitCtor<_Valid, _UElements...> = false>
1539         explicit constexpr
1540         tuple(tuple<_UElements...>&& __in)
1541         noexcept(__nothrow_constructible<_UElements...>())
1542         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1543         { __glibcxx_no_dangling_refs(_UElements&&); }
1545       // Allocator-extended constructors.
1547       template<typename _Alloc,
1548                _ImplicitDefaultCtor<is_object<_Alloc>::value> = true>
1549         _GLIBCXX20_CONSTEXPR
1550         tuple(allocator_arg_t __tag, const _Alloc& __a)
1551         : _Inherited(__tag, __a) { }
1553       template<typename _Alloc,
1554                _ExplicitDefaultCtor<is_object<_Alloc>::value> = false>
1555         _GLIBCXX20_CONSTEXPR
1556         explicit
1557         tuple(allocator_arg_t __tag, const _Alloc& __a)
1558         : _Inherited(__tag, __a) { }
1560       template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1561                _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1562         _GLIBCXX20_CONSTEXPR
1563         tuple(allocator_arg_t __tag, const _Alloc& __a,
1564               const _Elements&... __elements)
1565         : _Inherited(__tag, __a, __elements...) { }
1567       template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1568                _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1569         _GLIBCXX20_CONSTEXPR
1570         explicit
1571         tuple(allocator_arg_t __tag, const _Alloc& __a,
1572               const _Elements&... __elements)
1573         : _Inherited(__tag, __a, __elements...) { }
1575       template<typename _Alloc, typename... _UElements,
1576                bool _Valid = __valid_args<_UElements...>(),
1577                _ImplicitCtor<_Valid, _UElements...> = true>
1578         _GLIBCXX20_CONSTEXPR
1579         tuple(allocator_arg_t __tag, const _Alloc& __a,
1580               _UElements&&... __elements)
1581         : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1582         { __glibcxx_no_dangling_refs(_UElements&&); }
1584       template<typename _Alloc, typename... _UElements,
1585                  bool _Valid = __valid_args<_UElements...>(),
1586                _ExplicitCtor<_Valid, _UElements...> = false>
1587         _GLIBCXX20_CONSTEXPR
1588         explicit
1589         tuple(allocator_arg_t __tag, const _Alloc& __a,
1590               _UElements&&... __elements)
1591         : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1592         { __glibcxx_no_dangling_refs(_UElements&&); }
1594       template<typename _Alloc>
1595         _GLIBCXX20_CONSTEXPR
1596         tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1597         : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1599       template<typename _Alloc>
1600         _GLIBCXX20_CONSTEXPR
1601         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1602         : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1604       template<typename _Alloc, typename... _UElements,
1605                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1606                              && !__use_other_ctor<const tuple<_UElements...>&>(),
1607                _ImplicitCtor<_Valid, const _UElements&...> = true>
1608         _GLIBCXX20_CONSTEXPR
1609         tuple(allocator_arg_t __tag, const _Alloc& __a,
1610               const tuple<_UElements...>& __in)
1611         : _Inherited(__tag, __a,
1612                      static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1613         { __glibcxx_no_dangling_refs(const _UElements&); }
1615       template<typename _Alloc, typename... _UElements,
1616                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1617                              && !__use_other_ctor<const tuple<_UElements...>&>(),
1618                _ExplicitCtor<_Valid, const _UElements&...> = false>
1619         _GLIBCXX20_CONSTEXPR
1620         explicit
1621         tuple(allocator_arg_t __tag, const _Alloc& __a,
1622               const tuple<_UElements...>& __in)
1623         : _Inherited(__tag, __a,
1624                      static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1625         { __glibcxx_no_dangling_refs(const _UElements&); }
1627       template<typename _Alloc, typename... _UElements,
1628                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1629                              && !__use_other_ctor<tuple<_UElements...>&&>(),
1630                _ImplicitCtor<_Valid, _UElements...> = true>
1631         _GLIBCXX20_CONSTEXPR
1632         tuple(allocator_arg_t __tag, const _Alloc& __a,
1633               tuple<_UElements...>&& __in)
1634         : _Inherited(__tag, __a,
1635                      static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1636         { __glibcxx_no_dangling_refs(_UElements&&); }
1638       template<typename _Alloc, typename... _UElements,
1639                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1640                              && !__use_other_ctor<tuple<_UElements...>&&>(),
1641                _ExplicitCtor<_Valid, _UElements...> = false>
1642         _GLIBCXX20_CONSTEXPR
1643         explicit
1644         tuple(allocator_arg_t __tag, const _Alloc& __a,
1645               tuple<_UElements...>&& __in)
1646         : _Inherited(__tag, __a,
1647                      static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1648         { __glibcxx_no_dangling_refs(_UElements&&); }
1649 #endif // concepts && conditional_explicit
1651       // tuple assignment
1653 #if __cpp_concepts && __cpp_consteval // >= C++20
1654     private:
1655       template<typename... _UTypes>
1656         static consteval bool
1657         __assignable()
1658         {
1659           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1660             return __and_v<is_assignable<_Elements&, _UTypes>...>;
1661           else
1662             return false;
1663         }
1665       template<typename... _UTypes>
1666         static consteval bool
1667         __nothrow_assignable()
1668         {
1669           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1670             return __and_v<is_nothrow_assignable<_Elements&, _UTypes>...>;
1671           else
1672             return false;
1673         }
1675 #if __cpp_lib_ranges_zip // >= C++23
1676       template<typename... _UTypes>
1677         static consteval bool
1678         __const_assignable()
1679         {
1680           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1681             return __and_v<is_assignable<const _Elements&, _UTypes>...>;
1682           else
1683             return false;
1684         }
1685 #endif // C++23
1687 #if __cpp_lib_tuple_like // >= C++23
1688       template<typename _UTuple>
1689         static consteval bool
1690         __assignable_from_tuple_like()
1691         {
1692           return []<size_t... _Is>(index_sequence<_Is...>) {
1693             return __assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1694           }(index_sequence_for<_Elements...>{});
1695         }
1697       template<typename _UTuple>
1698         static consteval bool
1699         __const_assignable_from_tuple_like()
1700         {
1701           return []<size_t... _Is>(index_sequence<_Is...>) {
1702             return __const_assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1703           }(index_sequence_for<_Elements...>{});
1704         }
1705 #endif // C++23
1707     public:
1709       tuple& operator=(const tuple& __u) = delete;
1711       constexpr tuple&
1712       operator=(const tuple& __u)
1713       noexcept(__nothrow_assignable<const _Elements&...>())
1714       requires (__assignable<const _Elements&...>())
1715       {
1716         this->_M_assign(__u);
1717         return *this;
1718       }
1720       constexpr tuple&
1721       operator=(tuple&& __u)
1722       noexcept(__nothrow_assignable<_Elements...>())
1723       requires (__assignable<_Elements...>())
1724       {
1725         this->_M_assign(std::move(__u));
1726         return *this;
1727       }
1729       template<typename... _UTypes>
1730         requires (__assignable<const _UTypes&...>())
1731         constexpr tuple&
1732         operator=(const tuple<_UTypes...>& __u)
1733         noexcept(__nothrow_assignable<const _UTypes&...>())
1734         {
1735           this->_M_assign(__u);
1736           return *this;
1737         }
1739       template<typename... _UTypes>
1740         requires (__assignable<_UTypes...>())
1741         constexpr tuple&
1742         operator=(tuple<_UTypes...>&& __u)
1743         noexcept(__nothrow_assignable<_UTypes...>())
1744         {
1745           this->_M_assign(std::move(__u));
1746           return *this;
1747         }
1749 #if __cpp_lib_ranges_zip // >= C++23
1750       constexpr const tuple&
1751       operator=(const tuple& __u) const
1752       requires (__const_assignable<const _Elements&...>())
1753       {
1754         this->_M_assign(__u);
1755         return *this;
1756       }
1758       constexpr const tuple&
1759       operator=(tuple&& __u) const
1760       requires (__const_assignable<_Elements...>())
1761       {
1762         this->_M_assign(std::move(__u));
1763         return *this;
1764       }
1766       template<typename... _UTypes>
1767         constexpr const tuple&
1768         operator=(const tuple<_UTypes...>& __u) const
1769         requires (__const_assignable<const _UTypes&...>())
1770         {
1771           this->_M_assign(__u);
1772           return *this;
1773         }
1775       template<typename... _UTypes>
1776         constexpr const tuple&
1777         operator=(tuple<_UTypes...>&& __u) const
1778         requires (__const_assignable<_UTypes...>())
1779         {
1780           this->_M_assign(std::move(__u));
1781           return *this;
1782         }
1783 #endif // C++23
1785       template<typename _U1, typename _U2>
1786         requires (__assignable<const _U1&, const _U2&>())
1787         constexpr tuple&
1788         operator=(const pair<_U1, _U2>& __u)
1789         noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1790         {
1791           this->_M_head(*this) = __u.first;
1792           this->_M_tail(*this)._M_head(*this) = __u.second;
1793           return *this;
1794         }
1796       template<typename _U1, typename _U2>
1797         requires (__assignable<_U1, _U2>())
1798         constexpr tuple&
1799         operator=(pair<_U1, _U2>&& __u)
1800         noexcept(__nothrow_assignable<_U1, _U2>())
1801         {
1802           this->_M_head(*this) = std::forward<_U1>(__u.first);
1803           this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1804           return *this;
1805         }
1807 #if __cpp_lib_ranges_zip // >= C++23
1808       template<typename _U1, typename _U2>
1809         requires (__const_assignable<const _U1&, const _U2>())
1810         constexpr const tuple&
1811         operator=(const pair<_U1, _U2>& __u) const
1812         {
1813           this->_M_head(*this) = __u.first;
1814           this->_M_tail(*this)._M_head(*this) = __u.second;
1815           return *this;
1816         }
1818       template<typename _U1, typename _U2>
1819         requires (__const_assignable<_U1, _U2>())
1820         constexpr const tuple&
1821         operator=(pair<_U1, _U2>&& __u) const
1822         {
1823           this->_M_head(*this) = std::forward<_U1>(__u.first);
1824           this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1825           return *this;
1826         }
1827 #endif // C++23
1829 #if __cpp_lib_tuple_like // >= C++23
1830       template<__eligible_tuple_like<tuple> _UTuple>
1831         requires (__assignable_from_tuple_like<_UTuple>())
1832         constexpr tuple&
1833         operator=(_UTuple&& __u)
1834         {
1835           this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1836           return *this;
1837         }
1839       template<__eligible_tuple_like<tuple> _UTuple>
1840         requires (__const_assignable_from_tuple_like<_UTuple>())
1841         constexpr const tuple&
1842         operator=(_UTuple&& __u) const
1843         {
1844           this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1845           return *this;
1846         }
1848       template<__tuple_like _UTuple>
1849         requires (!__is_tuple_v<_UTuple>)
1850         friend constexpr bool
1851         operator==(const tuple& __t, const _UTuple& __u)
1852         {
1853           static_assert(sizeof...(_Elements) == tuple_size_v<_UTuple>,
1854               "tuple objects can only be compared if they have equal sizes.");
1855           return [&]<size_t... _Is>(index_sequence<_Is...>) {
1856             return (bool(std::get<_Is>(__t) == std::get<_Is>(__u))
1857                     && ...);
1858           }(index_sequence_for<_Elements...>{});
1859         }
1861       template<__tuple_like _UTuple,
1862                typename = make_index_sequence<tuple_size_v<_UTuple>>>
1863         struct __tuple_like_common_comparison_category;
1865       template<__tuple_like _UTuple, size_t... _Is>
1866         requires requires
1867           { typename void_t<__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>; }
1868         struct __tuple_like_common_comparison_category<_UTuple, index_sequence<_Is...>>
1869         {
1870           using type = common_comparison_category_t
1871             <__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>;
1872         };
1874       template<__tuple_like _UTuple>
1875         requires (!__is_tuple_v<_UTuple>)
1876         friend constexpr typename __tuple_like_common_comparison_category<_UTuple>::type
1877         operator<=>(const tuple& __t, const _UTuple& __u)
1878         {
1879           using _Cat = typename __tuple_like_common_comparison_category<_UTuple>::type;
1880           return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Elements...>());
1881         }
1882 #endif // C++23
1884 #else // ! (concepts && consteval)
1886     private:
1887       template<typename... _UElements>
1888         static constexpr
1889         __enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
1890         __assignable()
1891         { return __and_<is_assignable<_Elements&, _UElements>...>::value; }
1893       // Condition for noexcept-specifier of an assignment operator.
1894       template<typename... _UElements>
1895         static constexpr bool __nothrow_assignable()
1896         {
1897           return
1898             __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
1899         }
1901     public:
1903       _GLIBCXX20_CONSTEXPR
1904       tuple&
1905       operator=(__conditional_t<__assignable<const _Elements&...>(),
1906                                 const tuple&,
1907                                 const __nonesuch&> __in)
1908       noexcept(__nothrow_assignable<const _Elements&...>())
1909       {
1910         this->_M_assign(__in);
1911         return *this;
1912       }
1914       _GLIBCXX20_CONSTEXPR
1915       tuple&
1916       operator=(__conditional_t<__assignable<_Elements...>(),
1917                                 tuple&&,
1918                                 __nonesuch&&> __in)
1919       noexcept(__nothrow_assignable<_Elements...>())
1920       {
1921         this->_M_assign(std::move(__in));
1922         return *this;
1923       }
1925       template<typename... _UElements>
1926         _GLIBCXX20_CONSTEXPR
1927         __enable_if_t<__assignable<const _UElements&...>(), tuple&>
1928         operator=(const tuple<_UElements...>& __in)
1929         noexcept(__nothrow_assignable<const _UElements&...>())
1930         {
1931           this->_M_assign(__in);
1932           return *this;
1933         }
1935       template<typename... _UElements>
1936         _GLIBCXX20_CONSTEXPR
1937         __enable_if_t<__assignable<_UElements...>(), tuple&>
1938         operator=(tuple<_UElements...>&& __in)
1939         noexcept(__nothrow_assignable<_UElements...>())
1940         {
1941           this->_M_assign(std::move(__in));
1942           return *this;
1943         }
1944 #endif // concepts && consteval
1946       // tuple swap
1947       _GLIBCXX20_CONSTEXPR
1948       void
1949       swap(tuple& __in)
1950       noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
1951       { _Inherited::_M_swap(__in); }
1953 #if __cpp_lib_ranges_zip // >= C++23
1954       // As an extension, we constrain the const swap member function in order
1955       // to continue accepting explicit instantiation of tuples whose elements
1956       // are not all const swappable.  Without this constraint, such an
1957       // explicit instantiation would also instantiate the ill-formed body of
1958       // this function and yield a hard error.  This constraint shouldn't
1959       // affect the behavior of valid programs.
1960       constexpr void
1961       swap(const tuple& __in) const
1962       noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
1963       requires (is_swappable_v<const _Elements> && ...)
1964       { _Inherited::_M_swap(__in); }
1965 #endif // C++23
1966     };
1968 #if __cpp_deduction_guides >= 201606
1969   template<typename... _UTypes>
1970     tuple(_UTypes...) -> tuple<_UTypes...>;
1971   template<typename _T1, typename _T2>
1972     tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
1973   template<typename _Alloc, typename... _UTypes>
1974     tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
1975   template<typename _Alloc, typename _T1, typename _T2>
1976     tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
1977   template<typename _Alloc, typename... _UTypes>
1978     tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
1979 #endif
1981   // Explicit specialization, zero-element tuple.
1982   template<>
1983     class tuple<>
1984     {
1985     public:
1986       _GLIBCXX20_CONSTEXPR
1987       void swap(tuple&) noexcept { /* no-op */ }
1988 #if __cpp_lib_ranges_zip // >= C++23
1989       constexpr void swap(const tuple&) const noexcept { /* no-op */ }
1990 #endif
1991       // We need the default since we're going to define no-op
1992       // allocator constructors.
1993       tuple() = default;
1994       // No-op allocator constructors.
1995       template<typename _Alloc>
1996         _GLIBCXX20_CONSTEXPR
1997         tuple(allocator_arg_t, const _Alloc&) noexcept { }
1998       template<typename _Alloc>
1999         _GLIBCXX20_CONSTEXPR
2000         tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
2001     };
2003 #if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20
2004   /// Partial specialization, 2-element tuple.
2005   /// Includes construction and assignment from a pair.
2006   template<typename _T1, typename _T2>
2007     class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
2008     {
2009       typedef _Tuple_impl<0, _T1, _T2> _Inherited;
2011       // Constraint for non-explicit default constructor
2012       template<bool _Dummy, typename _U1, typename _U2>
2013         using _ImplicitDefaultCtor = __enable_if_t<
2014           _TupleConstraints<_Dummy, _U1, _U2>::
2015             __is_implicitly_default_constructible(),
2016           bool>;
2018       // Constraint for explicit default constructor
2019       template<bool _Dummy, typename _U1, typename _U2>
2020         using _ExplicitDefaultCtor = __enable_if_t<
2021           _TupleConstraints<_Dummy, _U1, _U2>::
2022             __is_explicitly_default_constructible(),
2023           bool>;
2025       template<bool _Dummy>
2026         using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
2028       // Constraint for non-explicit constructors
2029       template<bool _Cond, typename _U1, typename _U2>
2030         using _ImplicitCtor = __enable_if_t<
2031           _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
2032           bool>;
2034       // Constraint for non-explicit constructors
2035       template<bool _Cond, typename _U1, typename _U2>
2036         using _ExplicitCtor = __enable_if_t<
2037           _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
2038           bool>;
2040       template<typename _U1, typename _U2>
2041         static constexpr bool __assignable()
2042         {
2043           return __and_<is_assignable<_T1&, _U1>,
2044                         is_assignable<_T2&, _U2>>::value;
2045         }
2047       template<typename _U1, typename _U2>
2048         static constexpr bool __nothrow_assignable()
2049         {
2050           return __and_<is_nothrow_assignable<_T1&, _U1>,
2051                         is_nothrow_assignable<_T2&, _U2>>::value;
2052         }
2054       template<typename _U1, typename _U2>
2055         static constexpr bool __nothrow_constructible()
2056         {
2057           return __and_<is_nothrow_constructible<_T1, _U1>,
2058                             is_nothrow_constructible<_T2, _U2>>::value;
2059         }
2061       static constexpr bool __nothrow_default_constructible()
2062       {
2063         return __and_<is_nothrow_default_constructible<_T1>,
2064                       is_nothrow_default_constructible<_T2>>::value;
2065       }
2067       template<typename _U1>
2068         static constexpr bool __is_alloc_arg()
2069         { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
2071       /// @cond undocumented
2072 #undef __glibcxx_no_dangling_refs
2073       // Error if construction from _U1 and _U2 would create a dangling ref.
2074 #if __has_builtin(__reference_constructs_from_temporary) \
2075       && defined _GLIBCXX_DEBUG
2076 # define __glibcxx_no_dangling_refs(_U1, _U2) \
2077   static_assert(!__reference_constructs_from_temporary(_T1, _U1) \
2078                && !__reference_constructs_from_temporary(_T2, _U2), \
2079                 "std::tuple constructor creates a dangling reference")
2080 #else
2081 # define __glibcxx_no_dangling_refs(_U1, _U2)
2082 #endif
2083       /// @endcond
2085     public:
2086       template<bool _Dummy = true,
2087                _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
2088         constexpr
2089         tuple()
2090         noexcept(__nothrow_default_constructible())
2091         : _Inherited() { }
2093       template<bool _Dummy = true,
2094                _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
2095         explicit constexpr
2096         tuple()
2097         noexcept(__nothrow_default_constructible())
2098         : _Inherited() { }
2100       template<bool _Dummy = true,
2101                _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2102         constexpr
2103         tuple(const _T1& __a1, const _T2& __a2)
2104         noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2105         : _Inherited(__a1, __a2) { }
2107       template<bool _Dummy = true,
2108                _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2109         explicit constexpr
2110         tuple(const _T1& __a1, const _T2& __a2)
2111         noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2112         : _Inherited(__a1, __a2) { }
2114       template<typename _U1, typename _U2,
2115                _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
2116         constexpr
2117         tuple(_U1&& __a1, _U2&& __a2)
2118         noexcept(__nothrow_constructible<_U1, _U2>())
2119         : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2120         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2122       template<typename _U1, typename _U2,
2123                _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
2124         explicit constexpr
2125         tuple(_U1&& __a1, _U2&& __a2)
2126         noexcept(__nothrow_constructible<_U1, _U2>())
2127         : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2128         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2130       constexpr tuple(const tuple&) = default;
2132       constexpr tuple(tuple&&) = default;
2134       template<typename _U1, typename _U2,
2135                _ImplicitCtor<true, const _U1&, const _U2&> = true>
2136         constexpr
2137         tuple(const tuple<_U1, _U2>& __in)
2138         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2139         : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2140         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2142       template<typename _U1, typename _U2,
2143                _ExplicitCtor<true, const _U1&, const _U2&> = false>
2144         explicit constexpr
2145         tuple(const tuple<_U1, _U2>& __in)
2146         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2147         : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2148         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2150       template<typename _U1, typename _U2,
2151                _ImplicitCtor<true, _U1, _U2> = true>
2152         constexpr
2153         tuple(tuple<_U1, _U2>&& __in)
2154         noexcept(__nothrow_constructible<_U1, _U2>())
2155         : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2156         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2158       template<typename _U1, typename _U2,
2159                _ExplicitCtor<true, _U1, _U2> = false>
2160         explicit constexpr
2161         tuple(tuple<_U1, _U2>&& __in)
2162         noexcept(__nothrow_constructible<_U1, _U2>())
2163         : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2164         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2166       template<typename _U1, typename _U2,
2167                _ImplicitCtor<true, const _U1&, const _U2&> = true>
2168         constexpr
2169         tuple(const pair<_U1, _U2>& __in)
2170         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2171         : _Inherited(__in.first, __in.second)
2172         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2174       template<typename _U1, typename _U2,
2175                _ExplicitCtor<true, const _U1&, const _U2&> = false>
2176         explicit constexpr
2177         tuple(const pair<_U1, _U2>& __in)
2178         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2179         : _Inherited(__in.first, __in.second)
2180         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2182       template<typename _U1, typename _U2,
2183                _ImplicitCtor<true, _U1, _U2> = true>
2184         constexpr
2185         tuple(pair<_U1, _U2>&& __in)
2186         noexcept(__nothrow_constructible<_U1, _U2>())
2187         : _Inherited(std::forward<_U1>(__in.first),
2188                      std::forward<_U2>(__in.second))
2189         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2191       template<typename _U1, typename _U2,
2192                _ExplicitCtor<true, _U1, _U2> = false>
2193         explicit constexpr
2194         tuple(pair<_U1, _U2>&& __in)
2195         noexcept(__nothrow_constructible<_U1, _U2>())
2196         : _Inherited(std::forward<_U1>(__in.first),
2197                      std::forward<_U2>(__in.second))
2198         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2200       // Allocator-extended constructors.
2202       template<typename _Alloc,
2203                _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
2204         _GLIBCXX20_CONSTEXPR
2205         tuple(allocator_arg_t __tag, const _Alloc& __a)
2206         : _Inherited(__tag, __a) { }
2208       template<typename _Alloc,
2209                _ExplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = false>
2210         _GLIBCXX20_CONSTEXPR
2211         explicit
2212         tuple(allocator_arg_t __tag, const _Alloc& __a)
2213         : _Inherited(__tag, __a) { }
2215       template<typename _Alloc, bool _Dummy = true,
2216                _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2217         _GLIBCXX20_CONSTEXPR
2218         tuple(allocator_arg_t __tag, const _Alloc& __a,
2219               const _T1& __a1, const _T2& __a2)
2220         : _Inherited(__tag, __a, __a1, __a2) { }
2222       template<typename _Alloc, bool _Dummy = true,
2223                _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2224         explicit
2225         _GLIBCXX20_CONSTEXPR
2226         tuple(allocator_arg_t __tag, const _Alloc& __a,
2227               const _T1& __a1, const _T2& __a2)
2228         : _Inherited(__tag, __a, __a1, __a2) { }
2230       template<typename _Alloc, typename _U1, typename _U2,
2231                _ImplicitCtor<true, _U1, _U2> = true>
2232         _GLIBCXX20_CONSTEXPR
2233         tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
2234         : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2235                      std::forward<_U2>(__a2))
2236         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2238       template<typename _Alloc, typename _U1, typename _U2,
2239                _ExplicitCtor<true, _U1, _U2> = false>
2240         explicit
2241         _GLIBCXX20_CONSTEXPR
2242         tuple(allocator_arg_t __tag, const _Alloc& __a,
2243               _U1&& __a1, _U2&& __a2)
2244         : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2245                      std::forward<_U2>(__a2))
2246         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2248       template<typename _Alloc>
2249         _GLIBCXX20_CONSTEXPR
2250         tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
2251         : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
2253       template<typename _Alloc>
2254         _GLIBCXX20_CONSTEXPR
2255         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
2256         : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
2258       template<typename _Alloc, typename _U1, typename _U2,
2259                _ImplicitCtor<true, const _U1&, const _U2&> = true>
2260         _GLIBCXX20_CONSTEXPR
2261         tuple(allocator_arg_t __tag, const _Alloc& __a,
2262               const tuple<_U1, _U2>& __in)
2263         : _Inherited(__tag, __a,
2264                      static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2265         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2267       template<typename _Alloc, typename _U1, typename _U2,
2268                _ExplicitCtor<true, const _U1&, const _U2&> = false>
2269         explicit
2270         _GLIBCXX20_CONSTEXPR
2271         tuple(allocator_arg_t __tag, const _Alloc& __a,
2272               const tuple<_U1, _U2>& __in)
2273         : _Inherited(__tag, __a,
2274                      static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2275         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2277       template<typename _Alloc, typename _U1, typename _U2,
2278                _ImplicitCtor<true, _U1, _U2> = true>
2279         _GLIBCXX20_CONSTEXPR
2280         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2281         : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2282         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2284       template<typename _Alloc, typename _U1, typename _U2,
2285                _ExplicitCtor<true, _U1, _U2> = false>
2286         explicit
2287         _GLIBCXX20_CONSTEXPR
2288         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2289         : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2290         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2292       template<typename _Alloc, typename _U1, typename _U2,
2293                _ImplicitCtor<true, const _U1&, const _U2&> = true>
2294         _GLIBCXX20_CONSTEXPR
2295         tuple(allocator_arg_t __tag, const _Alloc& __a,
2296               const pair<_U1, _U2>& __in)
2297         : _Inherited(__tag, __a, __in.first, __in.second)
2298         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2300       template<typename _Alloc, typename _U1, typename _U2,
2301                _ExplicitCtor<true, const _U1&, const _U2&> = false>
2302         explicit
2303         _GLIBCXX20_CONSTEXPR
2304         tuple(allocator_arg_t __tag, const _Alloc& __a,
2305               const pair<_U1, _U2>& __in)
2306         : _Inherited(__tag, __a, __in.first, __in.second)
2307         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2309       template<typename _Alloc, typename _U1, typename _U2,
2310                _ImplicitCtor<true, _U1, _U2> = true>
2311         _GLIBCXX20_CONSTEXPR
2312         tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2313         : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2314                      std::forward<_U2>(__in.second))
2315         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2317       template<typename _Alloc, typename _U1, typename _U2,
2318                _ExplicitCtor<true, _U1, _U2> = false>
2319         explicit
2320         _GLIBCXX20_CONSTEXPR
2321         tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2322         : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2323                      std::forward<_U2>(__in.second))
2324         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2326       // Tuple assignment.
2328       _GLIBCXX20_CONSTEXPR
2329       tuple&
2330       operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
2331                                 const tuple&,
2332                                 const __nonesuch&> __in)
2333       noexcept(__nothrow_assignable<const _T1&, const _T2&>())
2334       {
2335         this->_M_assign(__in);
2336         return *this;
2337       }
2339       _GLIBCXX20_CONSTEXPR
2340       tuple&
2341       operator=(__conditional_t<__assignable<_T1, _T2>(),
2342                                 tuple&&,
2343                                 __nonesuch&&> __in)
2344       noexcept(__nothrow_assignable<_T1, _T2>())
2345       {
2346         this->_M_assign(std::move(__in));
2347         return *this;
2348       }
2350       template<typename _U1, typename _U2>
2351         _GLIBCXX20_CONSTEXPR
2352         __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2353         operator=(const tuple<_U1, _U2>& __in)
2354         noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2355         {
2356           this->_M_assign(__in);
2357           return *this;
2358         }
2360       template<typename _U1, typename _U2>
2361         _GLIBCXX20_CONSTEXPR
2362         __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2363         operator=(tuple<_U1, _U2>&& __in)
2364         noexcept(__nothrow_assignable<_U1, _U2>())
2365         {
2366           this->_M_assign(std::move(__in));
2367           return *this;
2368         }
2370       template<typename _U1, typename _U2>
2371         _GLIBCXX20_CONSTEXPR
2372         __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2373         operator=(const pair<_U1, _U2>& __in)
2374         noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2375         {
2376           this->_M_head(*this) = __in.first;
2377           this->_M_tail(*this)._M_head(*this) = __in.second;
2378           return *this;
2379         }
2381       template<typename _U1, typename _U2>
2382         _GLIBCXX20_CONSTEXPR
2383         __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2384         operator=(pair<_U1, _U2>&& __in)
2385         noexcept(__nothrow_assignable<_U1, _U2>())
2386         {
2387           this->_M_head(*this) = std::forward<_U1>(__in.first);
2388           this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
2389           return *this;
2390         }
2392       _GLIBCXX20_CONSTEXPR
2393       void
2394       swap(tuple& __in)
2395       noexcept(__and_<__is_nothrow_swappable<_T1>,
2396                       __is_nothrow_swappable<_T2>>::value)
2397       { _Inherited::_M_swap(__in); }
2398     };
2399 #endif // concepts && conditional_explicit
2401   /// class tuple_size
2402   template<typename... _Elements>
2403     struct tuple_size<tuple<_Elements...>>
2404     : public integral_constant<size_t, sizeof...(_Elements)> { };
2406 #if __cplusplus >= 201703L
2407   template<typename... _Types>
2408     inline constexpr size_t tuple_size_v<tuple<_Types...>>
2409       = sizeof...(_Types);
2411   template<typename... _Types>
2412     inline constexpr size_t tuple_size_v<const tuple<_Types...>>
2413       = sizeof...(_Types);
2414 #endif
2416   /// Trait to get the Ith element type from a tuple.
2417   template<size_t __i, typename... _Types>
2418     struct tuple_element<__i, tuple<_Types...>>
2419     {
2420       static_assert(__i < sizeof...(_Types), "tuple index must be in range");
2422       using type = typename _Nth_type<__i, _Types...>::type;
2423     };
2425   template<size_t __i, typename _Head, typename... _Tail>
2426     constexpr _Head&
2427     __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2428     { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2430   template<size_t __i, typename _Head, typename... _Tail>
2431     constexpr const _Head&
2432     __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2433     { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2435   // Deleted overload to improve diagnostics for invalid indices
2436   template<size_t __i, typename... _Types>
2437     __enable_if_t<(__i >= sizeof...(_Types))>
2438     __get_helper(const tuple<_Types...>&) = delete;
2440   /// Return a reference to the ith element of a tuple.
2441   template<size_t __i, typename... _Elements>
2442     constexpr __tuple_element_t<__i, tuple<_Elements...>>&
2443     get(tuple<_Elements...>& __t) noexcept
2444     { return std::__get_helper<__i>(__t); }
2446   /// Return a const reference to the ith element of a const tuple.
2447   template<size_t __i, typename... _Elements>
2448     constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
2449     get(const tuple<_Elements...>& __t) noexcept
2450     { return std::__get_helper<__i>(__t); }
2452   /// Return an rvalue reference to the ith element of a tuple rvalue.
2453   template<size_t __i, typename... _Elements>
2454     constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
2455     get(tuple<_Elements...>&& __t) noexcept
2456     {
2457       typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2458       return std::forward<__element_type>(std::__get_helper<__i>(__t));
2459     }
2461   /// Return a const rvalue reference to the ith element of a const tuple rvalue.
2462   template<size_t __i, typename... _Elements>
2463     constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
2464     get(const tuple<_Elements...>&& __t) noexcept
2465     {
2466       typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2467       return std::forward<const __element_type>(std::__get_helper<__i>(__t));
2468     }
2470   /// @cond undocumented
2471   // Deleted overload chosen for invalid indices.
2472   template<size_t __i, typename... _Elements>
2473     constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
2474     get(const tuple<_Elements...>&) = delete;
2475   /// @endcond
2477 #ifdef __cpp_lib_tuples_by_type // C++ >= 14
2478   /// Return a reference to the unique element of type _Tp of a tuple.
2479   template <typename _Tp, typename... _Types>
2480     constexpr _Tp&
2481     get(tuple<_Types...>& __t) noexcept
2482     {
2483       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2484       static_assert(__idx < sizeof...(_Types),
2485           "the type T in std::get<T> must occur exactly once in the tuple");
2486       return std::__get_helper<__idx>(__t);
2487     }
2489   /// Return a reference to the unique element of type _Tp of a tuple rvalue.
2490   template <typename _Tp, typename... _Types>
2491     constexpr _Tp&&
2492     get(tuple<_Types...>&& __t) noexcept
2493     {
2494       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2495       static_assert(__idx < sizeof...(_Types),
2496           "the type T in std::get<T> must occur exactly once in the tuple");
2497       return std::forward<_Tp>(std::__get_helper<__idx>(__t));
2498     }
2500   /// Return a const reference to the unique element of type _Tp of a tuple.
2501   template <typename _Tp, typename... _Types>
2502     constexpr const _Tp&
2503     get(const tuple<_Types...>& __t) noexcept
2504     {
2505       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2506       static_assert(__idx < sizeof...(_Types),
2507           "the type T in std::get<T> must occur exactly once in the tuple");
2508       return std::__get_helper<__idx>(__t);
2509     }
2511   /// Return a const reference to the unique element of type _Tp of
2512   /// a const tuple rvalue.
2513   template <typename _Tp, typename... _Types>
2514     constexpr const _Tp&&
2515     get(const tuple<_Types...>&& __t) noexcept
2516     {
2517       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2518       static_assert(__idx < sizeof...(_Types),
2519           "the type T in std::get<T> must occur exactly once in the tuple");
2520       return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
2521     }
2522 #endif
2524   // This class performs the comparison operations on tuples
2525   template<typename _Tp, typename _Up, size_t __i, size_t __size>
2526     struct __tuple_compare
2527     {
2528       static constexpr bool
2529       __eq(const _Tp& __t, const _Up& __u)
2530       {
2531         return bool(std::get<__i>(__t) == std::get<__i>(__u))
2532           && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
2533       }
2535       static constexpr bool
2536       __less(const _Tp& __t, const _Up& __u)
2537       {
2538         return bool(std::get<__i>(__t) < std::get<__i>(__u))
2539           || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
2540               && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
2541       }
2542     };
2544   template<typename _Tp, typename _Up, size_t __size>
2545     struct __tuple_compare<_Tp, _Up, __size, __size>
2546     {
2547       static constexpr bool
2548       __eq(const _Tp&, const _Up&) { return true; }
2550       static constexpr bool
2551       __less(const _Tp&, const _Up&) { return false; }
2552     };
2554   template<typename... _TElements, typename... _UElements>
2555     constexpr bool
2556     operator==(const tuple<_TElements...>& __t,
2557                const tuple<_UElements...>& __u)
2558     {
2559       static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2560           "tuple objects can only be compared if they have equal sizes.");
2561       using __compare = __tuple_compare<tuple<_TElements...>,
2562                                         tuple<_UElements...>,
2563                                         0, sizeof...(_TElements)>;
2564       return __compare::__eq(__t, __u);
2565     }
2567 #if __cpp_lib_three_way_comparison
2568   template<typename _Cat, typename _Tp, typename _Up>
2569     constexpr _Cat
2570     __tuple_cmp(const _Tp&, const _Up&, index_sequence<>)
2571     { return _Cat::equivalent; }
2573   template<typename _Cat, typename _Tp, typename _Up,
2574            size_t _Idx0, size_t... _Idxs>
2575     constexpr _Cat
2576     __tuple_cmp(const _Tp& __t, const _Up& __u,
2577                 index_sequence<_Idx0, _Idxs...>)
2578     {
2579       auto __c
2580         = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u));
2581       if (__c != 0)
2582         return __c;
2583       return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>());
2584     }
2586   template<typename... _Tps, typename... _Ups>
2587     constexpr
2588     common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
2589     operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
2590     {
2591       using _Cat
2592         = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
2593       return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
2594     }
2595 #else
2596   template<typename... _TElements, typename... _UElements>
2597     constexpr bool
2598     operator<(const tuple<_TElements...>& __t,
2599               const tuple<_UElements...>& __u)
2600     {
2601       static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2602           "tuple objects can only be compared if they have equal sizes.");
2603       using __compare = __tuple_compare<tuple<_TElements...>,
2604                                         tuple<_UElements...>,
2605                                         0, sizeof...(_TElements)>;
2606       return __compare::__less(__t, __u);
2607     }
2609   template<typename... _TElements, typename... _UElements>
2610     constexpr bool
2611     operator!=(const tuple<_TElements...>& __t,
2612                const tuple<_UElements...>& __u)
2613     { return !(__t == __u); }
2615   template<typename... _TElements, typename... _UElements>
2616     constexpr bool
2617     operator>(const tuple<_TElements...>& __t,
2618               const tuple<_UElements...>& __u)
2619     { return __u < __t; }
2621   template<typename... _TElements, typename... _UElements>
2622     constexpr bool
2623     operator<=(const tuple<_TElements...>& __t,
2624                const tuple<_UElements...>& __u)
2625     { return !(__u < __t); }
2627   template<typename... _TElements, typename... _UElements>
2628     constexpr bool
2629     operator>=(const tuple<_TElements...>& __t,
2630                const tuple<_UElements...>& __u)
2631     { return !(__t < __u); }
2632 #endif // three_way_comparison
2634   // NB: DR 705.
2635   /// Create a tuple containing copies of the arguments
2636   template<typename... _Elements>
2637     constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
2638     make_tuple(_Elements&&... __args)
2639     {
2640       typedef tuple<typename __decay_and_strip<_Elements>::__type...>
2641         __result_type;
2642       return __result_type(std::forward<_Elements>(__args)...);
2643     }
2645   // _GLIBCXX_RESOLVE_LIB_DEFECTS
2646   // 2275. Why is forward_as_tuple not constexpr?
2647   /// Create a tuple of lvalue or rvalue references to the arguments
2648   template<typename... _Elements>
2649     constexpr tuple<_Elements&&...>
2650     forward_as_tuple(_Elements&&... __args) noexcept
2651     { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2653   /// @cond undocumented
2654   template<size_t, typename, typename, size_t>
2655     struct __make_tuple_impl;
2657   template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
2658     struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
2659     : __make_tuple_impl<_Idx + 1,
2660                         tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
2661                         _Tuple, _Nm>
2662     { };
2664   template<size_t _Nm, typename _Tuple, typename... _Tp>
2665     struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
2666     {
2667       typedef tuple<_Tp...> __type;
2668     };
2670   template<typename _Tuple>
2671     struct __do_make_tuple
2672     : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
2673     { };
2675   // Returns the std::tuple equivalent of a tuple-like type.
2676   template<typename _Tuple>
2677     struct __make_tuple
2678     : public __do_make_tuple<__remove_cvref_t<_Tuple>>
2679     { };
2681   // Combines several std::tuple's into a single one.
2682   template<typename...>
2683     struct __combine_tuples;
2685   template<>
2686     struct __combine_tuples<>
2687     {
2688       typedef tuple<> __type;
2689     };
2691   template<typename... _Ts>
2692     struct __combine_tuples<tuple<_Ts...>>
2693     {
2694       typedef tuple<_Ts...> __type;
2695     };
2697   template<typename... _T1s, typename... _T2s, typename... _Rem>
2698     struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
2699     {
2700       typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
2701                                         _Rem...>::__type __type;
2702     };
2704   // Computes the result type of tuple_cat given a set of tuple-like types.
2705   template<typename... _Tpls>
2706     struct __tuple_cat_result
2707     {
2708       typedef typename __combine_tuples
2709         <typename __make_tuple<_Tpls>::__type...>::__type __type;
2710     };
2712   // Helper to determine the index set for the first tuple-like
2713   // type of a given set.
2714   template<typename...>
2715     struct __make_1st_indices;
2717   template<>
2718     struct __make_1st_indices<>
2719     {
2720       typedef _Index_tuple<> __type;
2721     };
2723   template<typename _Tp, typename... _Tpls>
2724     struct __make_1st_indices<_Tp, _Tpls...>
2725     {
2726       typedef typename _Build_index_tuple<tuple_size<
2727         typename remove_reference<_Tp>::type>::value>::__type __type;
2728     };
2730   // Performs the actual concatenation by step-wise expanding tuple-like
2731   // objects into the elements,  which are finally forwarded into the
2732   // result tuple.
2733   template<typename _Ret, typename _Indices, typename... _Tpls>
2734     struct __tuple_concater;
2736   template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2737     struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2738     {
2739       template<typename... _Us>
2740         static constexpr _Ret
2741         _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2742         {
2743           typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2744           typedef __tuple_concater<_Ret, __idx, _Tpls...>      __next;
2745           return __next::_S_do(std::forward<_Tpls>(__tps)...,
2746                                std::forward<_Us>(__us)...,
2747                                std::get<_Is>(std::forward<_Tp>(__tp))...);
2748         }
2749     };
2751   template<typename _Ret>
2752     struct __tuple_concater<_Ret, _Index_tuple<>>
2753     {
2754       template<typename... _Us>
2755         static constexpr _Ret
2756         _S_do(_Us&&... __us)
2757         {
2758           return _Ret(std::forward<_Us>(__us)...);
2759         }
2760     };
2762   template<typename... _Tps>
2763     struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2764     { };
2765   /// @endcond
2767   /// Create a `tuple` containing all elements from multiple tuple-like objects
2768 #if __cpp_lib_tuple_like // >= C++23
2769   template<__tuple_like... _Tpls>
2770 #else
2771   template<typename... _Tpls, typename = typename
2772            enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2773 #endif
2774     constexpr auto
2775     tuple_cat(_Tpls&&... __tpls)
2776     -> typename __tuple_cat_result<_Tpls...>::__type
2777     {
2778       typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2779       typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2780       typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2781       return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2782     }
2784   // _GLIBCXX_RESOLVE_LIB_DEFECTS
2785   // 2301. Why is tie not constexpr?
2786   /// Return a tuple of lvalue references bound to the arguments
2787   template<typename... _Elements>
2788     constexpr tuple<_Elements&...>
2789     tie(_Elements&... __args) noexcept
2790     { return tuple<_Elements&...>(__args...); }
2792   /// Exchange the values of two tuples
2793   template<typename... _Elements>
2794     _GLIBCXX20_CONSTEXPR
2795     inline
2796 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2797     // Constrained free swap overload, see p0185r1
2798     typename enable_if<__and_<__is_swappable<_Elements>...>::value
2799       >::type
2800 #else
2801     void
2802 #endif
2803     swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
2804     noexcept(noexcept(__x.swap(__y)))
2805     { __x.swap(__y); }
2807 #if __cpp_lib_ranges_zip // >= C++23
2808   template<typename... _Elements>
2809     requires (is_swappable_v<const _Elements> && ...)
2810     constexpr void
2811     swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2812     noexcept(noexcept(__x.swap(__y)))
2813     { __x.swap(__y); }
2814 #endif // C++23
2816 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2817   /// Exchange the values of two const tuples (if const elements can be swapped)
2818   template<typename... _Elements>
2819     _GLIBCXX20_CONSTEXPR
2820     typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2821     swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2822 #endif
2824   // A class (and instance) which can be used in 'tie' when an element
2825   // of a tuple is not required.
2826   // _GLIBCXX14_CONSTEXPR
2827   // 2933. PR for LWG 2773 could be clearer
2828   struct _Swallow_assign
2829   {
2830     template<class _Tp>
2831       _GLIBCXX14_CONSTEXPR const _Swallow_assign&
2832       operator=(const _Tp&) const
2833       { return *this; }
2834   };
2836   // _GLIBCXX_RESOLVE_LIB_DEFECTS
2837   // 2773. Making std::ignore constexpr
2838   /** Used with `std::tie` to ignore an element of a tuple
2839    *
2840    * When using `std::tie` to assign the elements of a tuple to variables,
2841    * unwanted elements can be ignored by using `std::ignore`. For example:
2842    *
2843    * ```
2844    * int x, y;
2845    * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3);
2846    * ```
2847    *
2848    * This assignment will perform `x=1; std::ignore=2; y=3;` which results
2849    * in the second element being ignored.
2850    *
2851    * @since C++11
2852    */
2853   _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{};
2855   /// Partial specialization for tuples
2856   template<typename... _Types, typename _Alloc>
2857     struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2859   // See stl_pair.h...
2860   /** "piecewise construction" using a tuple of arguments for each member.
2861    *
2862    * @param __first Arguments for the first member of the pair.
2863    * @param __second Arguments for the second member of the pair.
2864    *
2865    * The elements of each tuple will be used as the constructor arguments
2866    * for the data members of the pair.
2867   */
2868   template<class _T1, class _T2>
2869     template<typename... _Args1, typename... _Args2>
2870       _GLIBCXX20_CONSTEXPR
2871       inline
2872       pair<_T1, _T2>::
2873       pair(piecewise_construct_t,
2874            tuple<_Args1...> __first, tuple<_Args2...> __second)
2875       : pair(__first, __second,
2876              typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2877              typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2878       { }
2880   template<class _T1, class _T2>
2881     template<typename... _Args1, size_t... _Indexes1,
2882              typename... _Args2, size_t... _Indexes2>
2883       _GLIBCXX20_CONSTEXPR inline
2884       pair<_T1, _T2>::
2885       pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2886            _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2887       : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2888         second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2889       { }
2891 #if defined(__cpp_lib_apply) || defined(__cpp_lib_make_from_tuple) // C++ >= 17
2892   // Unpack a std::tuple into a type trait and use its value.
2893   // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2894   // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2895   // Otherwise the result is false (because we don't know if std::get throws).
2896   template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2897     inline constexpr bool __unpack_std_tuple = false;
2899   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2900     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2901       = _Trait<_Tp, _Up...>::value;
2903   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2904     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2905       = _Trait<_Tp, _Up&...>::value;
2907   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2908     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2909       = _Trait<_Tp, const _Up...>::value;
2911   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2912     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2913       = _Trait<_Tp, const _Up&...>::value;
2914 #endif
2916 #ifdef __cpp_lib_apply // C++ >= 17
2917   template <typename _Fn, typename _Tuple, size_t... _Idx>
2918     constexpr decltype(auto)
2919     __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2920     {
2921       return std::__invoke(std::forward<_Fn>(__f),
2922                            std::get<_Idx>(std::forward<_Tuple>(__t))...);
2923     }
2925 #if __cpp_lib_tuple_like // >= C++23
2926   template <typename _Fn, __tuple_like _Tuple>
2927 #else
2928   template <typename _Fn, typename _Tuple>
2929 #endif
2930     constexpr decltype(auto)
2931     apply(_Fn&& __f, _Tuple&& __t)
2932     noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2933     {
2934       using _Indices
2935         = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2936       return std::__apply_impl(std::forward<_Fn>(__f),
2937                                std::forward<_Tuple>(__t),
2938                                _Indices{});
2939     }
2940 #endif
2942 #ifdef __cpp_lib_make_from_tuple // C++ >= 17
2943   template <typename _Tp, typename _Tuple, size_t... _Idx>
2944     constexpr _Tp
2945     __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
2946     { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
2948 #if __cpp_lib_tuple_like // >= C++23
2949   template <typename _Tp, __tuple_like _Tuple>
2950 #else
2951   template <typename _Tp, typename _Tuple>
2952 #endif
2953     constexpr _Tp
2954     make_from_tuple(_Tuple&& __t)
2955     noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
2956     {
2957       constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
2958 #if __has_builtin(__reference_constructs_from_temporary)
2959       if constexpr (__n == 1)
2960         {
2961           using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
2962           static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
2963         }
2964 #endif
2965       return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
2966                                          make_index_sequence<__n>{});
2967     }
2968 #endif
2970 #if __cpp_lib_tuple_like // >= C++23
2971   template<__tuple_like _TTuple, __tuple_like _UTuple,
2972            template<typename> class _TQual, template<typename> class _UQual,
2973            typename = make_index_sequence<tuple_size_v<_TTuple>>>
2974   struct __tuple_like_common_reference;
2976   template<__tuple_like _TTuple, __tuple_like _UTuple,
2977            template<typename> class _TQual, template<typename> class _UQual,
2978            size_t... _Is>
2979     requires requires
2980       { typename tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2981                                           _UQual<tuple_element_t<_Is, _UTuple>>>...>; }
2982   struct __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual, index_sequence<_Is...>>
2983   {
2984     using type = tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2985                                           _UQual<tuple_element_t<_Is, _UTuple>>>...>;
2986   };
2988   template<__tuple_like _TTuple, __tuple_like _UTuple,
2989            template<typename> class _TQual, template<typename> class _UQual>
2990     requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
2991       && is_same_v<_TTuple, decay_t<_TTuple>>
2992       && is_same_v<_UTuple, decay_t<_UTuple>>
2993       && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
2994       && requires { typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type; }
2995   struct basic_common_reference<_TTuple, _UTuple, _TQual, _UQual>
2996   {
2997     using type = typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type;
2998   };
3000   template<__tuple_like _TTuple, __tuple_like _UTuple,
3001            typename = make_index_sequence<tuple_size_v<_TTuple>>>
3002   struct __tuple_like_common_type;
3004   template<__tuple_like _TTuple, __tuple_like _UTuple, size_t... _Is>
3005     requires requires
3006       { typename tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3007                                    tuple_element_t<_Is, _UTuple>>...>; }
3008   struct __tuple_like_common_type<_TTuple, _UTuple, index_sequence<_Is...>>
3009   {
3010     using type = tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3011                                      tuple_element_t<_Is, _UTuple>>...>;
3012   };
3014   template<__tuple_like _TTuple, __tuple_like _UTuple>
3015     requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
3016       && is_same_v<_TTuple, decay_t<_TTuple>>
3017       && is_same_v<_UTuple, decay_t<_UTuple>>
3018       && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
3019       && requires { typename __tuple_like_common_type<_TTuple, _UTuple>::type; }
3020   struct common_type<_TTuple, _UTuple>
3021   {
3022     using type = typename __tuple_like_common_type<_TTuple, _UTuple>::type;
3023   };
3024 #endif // C++23
3026   /// @}
3028 #undef __glibcxx_no_dangling_refs
3030 _GLIBCXX_END_NAMESPACE_VERSION
3031 } // namespace std
3033 #endif // C++11
3035 #endif // _GLIBCXX_TUPLE