Daily bump.
[official-gcc.git] / libstdc++-v3 / include / std / tuple
blob93b649e7d21109e2c91a2b02c8513e76f454dde3
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 #define __glibcxx_want_constrained_equality
55 #include <bits/version.h>
57 namespace std _GLIBCXX_VISIBILITY(default)
59 _GLIBCXX_BEGIN_NAMESPACE_VERSION
61   /**
62    *  @addtogroup utilities
63    *  @{
64    */
66   template<typename... _Elements>
67     class tuple;
69   template<typename _Tp>
70     struct __is_empty_non_tuple : is_empty<_Tp> { };
72   // Using EBO for elements that are tuples causes ambiguous base errors.
73   template<typename _El0, typename... _El>
74     struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { };
76   // Use the Empty Base-class Optimization for empty, non-final types.
77   template<typename _Tp>
78     using __empty_not_final
79     = __conditional_t<__is_final(_Tp), false_type,
80                       __is_empty_non_tuple<_Tp>>;
82   template<size_t _Idx, typename _Head,
83            bool = __empty_not_final<_Head>::value>
84     struct _Head_base;
86 #if __has_cpp_attribute(__no_unique_address__)
87   template<size_t _Idx, typename _Head>
88     struct _Head_base<_Idx, _Head, true>
89     {
90       constexpr _Head_base()
91       : _M_head_impl() { }
93       constexpr _Head_base(const _Head& __h)
94       : _M_head_impl(__h) { }
96       constexpr _Head_base(const _Head_base&) = default;
97       constexpr _Head_base(_Head_base&&) = default;
99       template<typename _UHead>
100         constexpr _Head_base(_UHead&& __h)
101         : _M_head_impl(std::forward<_UHead>(__h)) { }
103       _GLIBCXX20_CONSTEXPR
104       _Head_base(allocator_arg_t, __uses_alloc0)
105       : _M_head_impl() { }
107       template<typename _Alloc>
108         _GLIBCXX20_CONSTEXPR
109         _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
110         : _M_head_impl(allocator_arg, *__a._M_a) { }
112       template<typename _Alloc>
113         _GLIBCXX20_CONSTEXPR
114         _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
115         : _M_head_impl(*__a._M_a) { }
117       template<typename _UHead>
118         _GLIBCXX20_CONSTEXPR
119         _Head_base(__uses_alloc0, _UHead&& __uhead)
120         : _M_head_impl(std::forward<_UHead>(__uhead)) { }
122       template<typename _Alloc, typename _UHead>
123         _GLIBCXX20_CONSTEXPR
124         _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
125         : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
126         { }
128       template<typename _Alloc, typename _UHead>
129         _GLIBCXX20_CONSTEXPR
130         _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
131         : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
133       static constexpr _Head&
134       _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
136       static constexpr const _Head&
137       _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
139       [[__no_unique_address__]] _Head _M_head_impl;
140     };
141 #else
142   template<size_t _Idx, typename _Head>
143     struct _Head_base<_Idx, _Head, true>
144     : public _Head
145     {
146       constexpr _Head_base()
147       : _Head() { }
149       constexpr _Head_base(const _Head& __h)
150       : _Head(__h) { }
152       constexpr _Head_base(const _Head_base&) = default;
153       constexpr _Head_base(_Head_base&&) = default;
155       template<typename _UHead>
156         constexpr _Head_base(_UHead&& __h)
157         : _Head(std::forward<_UHead>(__h)) { }
159       _GLIBCXX20_CONSTEXPR
160       _Head_base(allocator_arg_t, __uses_alloc0)
161       : _Head() { }
163       template<typename _Alloc>
164         _GLIBCXX20_CONSTEXPR
165         _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
166         : _Head(allocator_arg, *__a._M_a) { }
168       template<typename _Alloc>
169         _GLIBCXX20_CONSTEXPR
170         _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
171         : _Head(*__a._M_a) { }
173       template<typename _UHead>
174         _GLIBCXX20_CONSTEXPR
175         _Head_base(__uses_alloc0, _UHead&& __uhead)
176         : _Head(std::forward<_UHead>(__uhead)) { }
178       template<typename _Alloc, typename _UHead>
179         _GLIBCXX20_CONSTEXPR
180         _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
181         : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
183       template<typename _Alloc, typename _UHead>
184         _GLIBCXX20_CONSTEXPR
185         _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
186         : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
188       static constexpr _Head&
189       _M_head(_Head_base& __b) noexcept { return __b; }
191       static constexpr const _Head&
192       _M_head(const _Head_base& __b) noexcept { return __b; }
193     };
194 #endif
196   template<size_t _Idx, typename _Head>
197     struct _Head_base<_Idx, _Head, false>
198     {
199       constexpr _Head_base()
200       : _M_head_impl() { }
202       constexpr _Head_base(const _Head& __h)
203       : _M_head_impl(__h) { }
205       constexpr _Head_base(const _Head_base&) = default;
206       constexpr _Head_base(_Head_base&&) = default;
208       template<typename _UHead>
209         constexpr _Head_base(_UHead&& __h)
210         : _M_head_impl(std::forward<_UHead>(__h)) { }
212       _GLIBCXX20_CONSTEXPR
213       _Head_base(allocator_arg_t, __uses_alloc0)
214       : _M_head_impl() { }
216       template<typename _Alloc>
217         _GLIBCXX20_CONSTEXPR
218         _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
219         : _M_head_impl(allocator_arg, *__a._M_a) { }
221       template<typename _Alloc>
222         _GLIBCXX20_CONSTEXPR
223         _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
224         : _M_head_impl(*__a._M_a) { }
226       template<typename _UHead>
227         _GLIBCXX20_CONSTEXPR
228         _Head_base(__uses_alloc0, _UHead&& __uhead)
229         : _M_head_impl(std::forward<_UHead>(__uhead)) { }
231       template<typename _Alloc, typename _UHead>
232         _GLIBCXX20_CONSTEXPR
233         _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
234         : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
235         { }
237       template<typename _Alloc, typename _UHead>
238         _GLIBCXX20_CONSTEXPR
239         _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
240         : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
242       static constexpr _Head&
243       _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
245       static constexpr const _Head&
246       _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
248       _Head _M_head_impl;
249     };
251 #if __cpp_lib_tuple_like // >= C++23
252   struct __tuple_like_tag_t { explicit __tuple_like_tag_t() = default; };
254   // This forward declaration is used by the operator<=> overload for
255   // tuple-like types.
256   template<typename _Cat, typename _Tp, typename _Up, typename _IndexSeq>
257     constexpr _Cat
258     __tuple_cmp(const _Tp& __t, const _Up& __u, _IndexSeq);
259 #endif // C++23
261   /**
262    * Contains the actual implementation of the @c tuple template, stored
263    * as a recursive inheritance hierarchy from the first element (most
264    * derived class) to the last (least derived class). The @c Idx
265    * parameter gives the 0-based index of the element stored at this
266    * point in the hierarchy; we use it to implement a constant-time
267    * get() operation.
268    */
269   template<size_t _Idx, typename... _Elements>
270     struct _Tuple_impl;
272   /**
273    * Recursive tuple implementation. Here we store the @c Head element
274    * and derive from a @c Tuple_impl containing the remaining elements
275    * (which contains the @c Tail).
276    */
277   template<size_t _Idx, typename _Head, typename... _Tail>
278     struct _Tuple_impl<_Idx, _Head, _Tail...>
279     : public _Tuple_impl<_Idx + 1, _Tail...>,
280       private _Head_base<_Idx, _Head>
281     {
282       template<size_t, typename...> friend struct _Tuple_impl;
284       typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
285       typedef _Head_base<_Idx, _Head> _Base;
287       static constexpr _Head&
288       _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
290       static constexpr const _Head&
291       _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
293       static constexpr _Inherited&
294       _M_tail(_Tuple_impl& __t) noexcept { return __t; }
296       static constexpr const _Inherited&
297       _M_tail(const _Tuple_impl& __t) noexcept { return __t; }
299       constexpr _Tuple_impl()
300       : _Inherited(), _Base() { }
302       explicit constexpr
303       _Tuple_impl(const _Head& __head, const _Tail&... __tail)
304       : _Inherited(__tail...), _Base(__head)
305       { }
307       template<typename _UHead, typename... _UTail,
308                typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
309         explicit constexpr
310         _Tuple_impl(_UHead&& __head, _UTail&&... __tail)
311         : _Inherited(std::forward<_UTail>(__tail)...),
312           _Base(std::forward<_UHead>(__head))
313         { }
315       constexpr _Tuple_impl(const _Tuple_impl&) = default;
317       // _GLIBCXX_RESOLVE_LIB_DEFECTS
318       // 2729. Missing SFINAE on std::pair::operator=
319       _Tuple_impl& operator=(const _Tuple_impl&) = delete;
321       _Tuple_impl(_Tuple_impl&&) = default;
323       template<typename... _UElements>
324         constexpr
325         _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
326         : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
327           _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
328         { }
330       template<typename _UHead, typename... _UTails>
331         constexpr
332         _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
333         : _Inherited(std::move
334                      (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
335           _Base(std::forward<_UHead>
336                 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
337         { }
339 #if __cpp_lib_ranges_zip // >= C++23
340       template<typename... _UElements>
341         constexpr
342         _Tuple_impl(_Tuple_impl<_Idx, _UElements...>& __in)
343         : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
344           _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
345         { }
347       template<typename _UHead, typename... _UTails>
348         constexpr
349         _Tuple_impl(const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
350         : _Inherited(std::move
351                      (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
352           _Base(std::forward<const _UHead>
353                 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
354         { }
355 #endif // C++23
357 #if __cpp_lib_tuple_like // >= C++23
358       template<typename _UTuple, size_t... _Is>
359         constexpr
360         _Tuple_impl(__tuple_like_tag_t, _UTuple&& __u, index_sequence<_Is...>)
361         : _Tuple_impl(std::get<_Is>(std::forward<_UTuple>(__u))...)
362         { }
363 #endif // C++23
365       template<typename _Alloc>
366         _GLIBCXX20_CONSTEXPR
367         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
368         : _Inherited(__tag, __a),
369           _Base(__tag, __use_alloc<_Head>(__a))
370         { }
372       template<typename _Alloc>
373         _GLIBCXX20_CONSTEXPR
374         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
375                     const _Head& __head, const _Tail&... __tail)
376         : _Inherited(__tag, __a, __tail...),
377           _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head)
378         { }
380       template<typename _Alloc, typename _UHead, typename... _UTail,
381                typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
382         _GLIBCXX20_CONSTEXPR
383         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
384                     _UHead&& __head, _UTail&&... __tail)
385         : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
386           _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
387                 std::forward<_UHead>(__head))
388         { }
390       template<typename _Alloc>
391         _GLIBCXX20_CONSTEXPR
392         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
393                     const _Tuple_impl& __in)
394         : _Inherited(__tag, __a, _M_tail(__in)),
395           _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in))
396         { }
398       template<typename _Alloc>
399         _GLIBCXX20_CONSTEXPR
400         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
401                     _Tuple_impl&& __in)
402         : _Inherited(__tag, __a, std::move(_M_tail(__in))),
403           _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
404                 std::forward<_Head>(_M_head(__in)))
405         { }
407       template<typename _Alloc, typename _UHead, typename... _UTails>
408         _GLIBCXX20_CONSTEXPR
409         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
410                     const _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
411         : _Inherited(__tag, __a,
412                      _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
413           _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
414                 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
415         { }
417       template<typename _Alloc, typename _UHead, typename... _UTails>
418         _GLIBCXX20_CONSTEXPR
419         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
420                     _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
421         : _Inherited(__tag, __a, std::move
422                      (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
423           _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
424                 std::forward<_UHead>
425                 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
426         { }
428 #if __cpp_lib_ranges_zip // >= C++23
429       template<typename _Alloc, typename _UHead, typename... _UTails>
430         constexpr
431         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
432                     _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
433         : _Inherited(__tag, __a,
434                      _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
435           _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
436                 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
437         { }
439       template<typename _Alloc, typename _UHead, typename... _UTails>
440         constexpr
441         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
442                     const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
443         : _Inherited(__tag, __a, std::move
444                      (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
445           _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
446                 std::forward<const _UHead>
447                 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
448         { }
449 #endif // C++23
451 #if __cpp_lib_tuple_like // >= C++23
452       template<typename _Alloc, typename _UTuple, size_t... _Is>
453         constexpr
454         _Tuple_impl(__tuple_like_tag_t, allocator_arg_t __tag, const _Alloc& __a,
455                     _UTuple&& __u, index_sequence<_Is...>)
456         : _Tuple_impl(__tag, __a, std::get<_Is>(std::forward<_UTuple>(__u))...)
457         { }
458 #endif // C++23
460       template<typename... _UElements>
461         _GLIBCXX20_CONSTEXPR
462         void
463         _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in)
464         {
465           _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
466           _M_tail(*this)._M_assign(
467               _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
468         }
470       template<typename _UHead, typename... _UTails>
471         _GLIBCXX20_CONSTEXPR
472         void
473         _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
474         {
475           _M_head(*this) = std::forward<_UHead>
476             (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
477           _M_tail(*this)._M_assign(
478               std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
479         }
481 #if __cpp_lib_ranges_zip // >= C++23
482       template<typename... _UElements>
483         constexpr void
484         _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) const
485         {
486           _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
487           _M_tail(*this)._M_assign(
488               _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
489         }
491       template<typename _UHead, typename... _UTails>
492         constexpr void
493         _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) const
494         {
495           _M_head(*this) = std::forward<_UHead>
496             (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
497           _M_tail(*this)._M_assign(
498               std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
499         }
500 #endif // C++23
502 #if __cpp_lib_tuple_like // >= C++23
503       template<typename _UTuple>
504         constexpr void
505         _M_assign(__tuple_like_tag_t __tag, _UTuple&& __u)
506         {
507           _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u));
508           _M_tail(*this)._M_assign(__tag, std::forward<_UTuple>(__u));
509         }
511       template<typename _UTuple>
512         constexpr void
513         _M_assign(__tuple_like_tag_t __tag, _UTuple&& __u) const
514         {
515           _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u));
516           _M_tail(*this)._M_assign(__tag, std::forward<_UTuple>(__u));
517         }
518 #endif // C++23
520     protected:
521       _GLIBCXX20_CONSTEXPR
522       void
523       _M_swap(_Tuple_impl& __in)
524       {
525         using std::swap;
526         swap(_M_head(*this), _M_head(__in));
527         _Inherited::_M_swap(_M_tail(__in));
528       }
530 #if __cpp_lib_ranges_zip // >= C++23
531       constexpr void
532       _M_swap(const _Tuple_impl& __in) const
533       {
534         using std::swap;
535         swap(_M_head(*this), _M_head(__in));
536         _Inherited::_M_swap(_M_tail(__in));
537       }
538 #endif // C++23
539     };
541   // Basis case of inheritance recursion.
542   template<size_t _Idx, typename _Head>
543     struct _Tuple_impl<_Idx, _Head>
544     : private _Head_base<_Idx, _Head>
545     {
546       template<size_t, typename...> friend struct _Tuple_impl;
548       typedef _Head_base<_Idx, _Head> _Base;
550       static constexpr _Head&
551       _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
553       static constexpr const _Head&
554       _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
556       constexpr
557       _Tuple_impl()
558       : _Base() { }
560       explicit constexpr
561       _Tuple_impl(const _Head& __head)
562       : _Base(__head)
563       { }
565       template<typename _UHead>
566         explicit constexpr
567         _Tuple_impl(_UHead&& __head)
568         : _Base(std::forward<_UHead>(__head))
569         { }
571       constexpr _Tuple_impl(const _Tuple_impl&) = default;
573       // _GLIBCXX_RESOLVE_LIB_DEFECTS
574       // 2729. Missing SFINAE on std::pair::operator=
575       _Tuple_impl& operator=(const _Tuple_impl&) = delete;
577 #if _GLIBCXX_INLINE_VERSION
578       _Tuple_impl(_Tuple_impl&&) = default;
579 #else
580       constexpr
581       _Tuple_impl(_Tuple_impl&& __in)
582       noexcept(is_nothrow_move_constructible<_Head>::value)
583       : _Base(static_cast<_Base&&>(__in))
584       { }
585 #endif
587       template<typename _UHead>
588         constexpr
589         _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in)
590         : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
591         { }
593       template<typename _UHead>
594         constexpr
595         _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in)
596         : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
597         { }
599 #if __cpp_lib_ranges_zip // >= C++23
600       template<typename _UHead>
601         constexpr
602         _Tuple_impl(_Tuple_impl<_Idx, _UHead>& __in)
603         : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
604         { }
606       template<typename _UHead>
607         constexpr
608         _Tuple_impl(const _Tuple_impl<_Idx, _UHead>&& __in)
609         : _Base(std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
610         { }
611 #endif // C++23
613 #if __cpp_lib_tuple_like // >= C++23
614       template<typename _UTuple>
615         constexpr
616         _Tuple_impl(__tuple_like_tag_t, _UTuple&& __u, index_sequence<0>)
617         : _Tuple_impl(std::get<0>(std::forward<_UTuple>(__u)))
618         { }
619 #endif // C++23
621       template<typename _Alloc>
622         _GLIBCXX20_CONSTEXPR
623         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
624         : _Base(__tag, __use_alloc<_Head>(__a))
625         { }
627       template<typename _Alloc>
628         _GLIBCXX20_CONSTEXPR
629         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
630                     const _Head& __head)
631         : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), __head)
632         { }
634       template<typename _Alloc, typename _UHead>
635         _GLIBCXX20_CONSTEXPR
636         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
637                     _UHead&& __head)
638         : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
639                 std::forward<_UHead>(__head))
640         { }
642       template<typename _Alloc>
643         _GLIBCXX20_CONSTEXPR
644         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
645                     const _Tuple_impl& __in)
646         : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), _M_head(__in))
647         { }
649       template<typename _Alloc>
650         _GLIBCXX20_CONSTEXPR
651         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
652                     _Tuple_impl&& __in)
653         : _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
654                 std::forward<_Head>(_M_head(__in)))
655         { }
657       template<typename _Alloc, typename _UHead>
658         _GLIBCXX20_CONSTEXPR
659         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
660                     const _Tuple_impl<_Idx, _UHead>& __in)
661         : _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
662                 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
663         { }
665       template<typename _Alloc, typename _UHead>
666         _GLIBCXX20_CONSTEXPR
667         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
668                     _Tuple_impl<_Idx, _UHead>&& __in)
669         : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
670                 std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
671         { }
673 #if __cpp_lib_ranges_zip // >= C++23
674       template<typename _Alloc, typename _UHead>
675         constexpr
676         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
677                     _Tuple_impl<_Idx, _UHead>& __in)
678         : _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
679                 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
680         { }
682       template<typename _Alloc, typename _UHead>
683         constexpr
684         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
685                     const _Tuple_impl<_Idx, _UHead>&& __in)
686         : _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
687                 std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
688         { }
689 #endif // C++23
691 #if __cpp_lib_tuple_like // >= C++23
692       template<typename _Alloc, typename _UTuple>
693         constexpr
694         _Tuple_impl(__tuple_like_tag_t, allocator_arg_t __tag, const _Alloc& __a,
695                     _UTuple&& __u, index_sequence<0>)
696         : _Tuple_impl(__tag, __a, std::get<0>(std::forward<_UTuple>(__u)))
697         { }
698 #endif // C++23
700       template<typename _UHead>
701         _GLIBCXX20_CONSTEXPR
702         void
703         _M_assign(const _Tuple_impl<_Idx, _UHead>& __in)
704         {
705           _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
706         }
708       template<typename _UHead>
709         _GLIBCXX20_CONSTEXPR
710         void
711         _M_assign(_Tuple_impl<_Idx, _UHead>&& __in)
712         {
713           _M_head(*this)
714             = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
715         }
717 #if __cpp_lib_ranges_zip // >= C++23
718       template<typename _UHead>
719         constexpr void
720         _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) const
721         {
722           _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
723         }
725       template<typename _UHead>
726         constexpr void
727         _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) const
728         {
729           _M_head(*this)
730             = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
731         }
732 #endif // C++23
734 #if __cpp_lib_tuple_like // >= C++23
735     template<typename _UTuple>
736       constexpr void
737       _M_assign(__tuple_like_tag_t, _UTuple&& __u)
738       { _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); }
740     template<typename _UTuple>
741       constexpr void
742       _M_assign(__tuple_like_tag_t, _UTuple&& __u) const
743       { _M_head(*this) = std::get<_Idx>(std::forward<_UTuple>(__u)); }
744 #endif // C++23
746     protected:
747       _GLIBCXX20_CONSTEXPR
748       void
749       _M_swap(_Tuple_impl& __in)
750       {
751         using std::swap;
752         swap(_M_head(*this), _M_head(__in));
753       }
755 #if __cpp_lib_ranges_zip // >= C++23
756       constexpr void
757       _M_swap(const _Tuple_impl& __in) const
758       {
759         using std::swap;
760         swap(_M_head(*this), _M_head(__in));
761       }
762 #endif // C++23
763     };
765   // Concept utility functions, reused in conditionally-explicit
766   // constructors.
767   template<bool, typename... _Types>
768     struct _TupleConstraints
769     {
770       template<typename... _UTypes>
771         using __constructible = __and_<is_constructible<_Types, _UTypes>...>;
773       template<typename... _UTypes>
774         using __convertible = __and_<is_convertible<_UTypes, _Types>...>;
776       // Constraint for a non-explicit constructor.
777       // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
778       // and every Ui is implicitly convertible to Ti.
779       template<typename... _UTypes>
780         static constexpr bool __is_implicitly_constructible()
781         {
782           return __and_<__constructible<_UTypes...>,
783                         __convertible<_UTypes...>
784                         >::value;
785         }
787       // Constraint for a non-explicit constructor.
788       // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
789       // but not every Ui is implicitly convertible to Ti.
790       template<typename... _UTypes>
791         static constexpr bool __is_explicitly_constructible()
792         {
793           return __and_<__constructible<_UTypes...>,
794                         __not_<__convertible<_UTypes...>>
795                         >::value;
796         }
798       static constexpr bool __is_implicitly_default_constructible()
799       {
800         return __and_<std::__is_implicitly_default_constructible<_Types>...
801                       >::value;
802       }
804       static constexpr bool __is_explicitly_default_constructible()
805       {
806         return __and_<is_default_constructible<_Types>...,
807                       __not_<__and_<
808                         std::__is_implicitly_default_constructible<_Types>...>
809                       >>::value;
810       }
811     };
813   // Partial specialization used when a required precondition isn't met,
814   // e.g. when sizeof...(_Types) != sizeof...(_UTypes).
815   template<typename... _Types>
816     struct _TupleConstraints<false, _Types...>
817     {
818       template<typename... _UTypes>
819         static constexpr bool __is_implicitly_constructible()
820         { return false; }
822       template<typename... _UTypes>
823         static constexpr bool __is_explicitly_constructible()
824         { return false; }
825     };
827   /// Primary class template, tuple
828   template<typename... _Elements>
829     class tuple : public _Tuple_impl<0, _Elements...>
830     {
831       using _Inherited = _Tuple_impl<0, _Elements...>;
833 #if __cpp_concepts && __cpp_consteval && __cpp_conditional_explicit // >= C++20
834       template<typename... _UTypes>
835         static consteval bool
836         __constructible()
837         {
838           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
839             return __and_v<is_constructible<_Elements, _UTypes>...>;
840           else
841             return false;
842         }
844       template<typename... _UTypes>
845         static consteval bool
846         __nothrow_constructible()
847         {
848           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
849             return __and_v<is_nothrow_constructible<_Elements, _UTypes>...>;
850           else
851             return false;
852         }
854       template<typename... _UTypes>
855         static consteval bool
856         __convertible()
857         {
858           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
859             return __and_v<is_convertible<_UTypes, _Elements>...>;
860           else
861             return false;
862         }
864       // _GLIBCXX_RESOLVE_LIB_DEFECTS
865       // 3121. tuple constructor constraints for UTypes&&... overloads
866       template<typename... _UTypes>
867         static consteval bool
868         __disambiguating_constraint()
869         {
870           if constexpr (sizeof...(_Elements) != sizeof...(_UTypes))
871             return false;
872           else if constexpr (sizeof...(_Elements) == 1)
873             {
874               using _U0 = typename _Nth_type<0, _UTypes...>::type;
875               return !is_same_v<remove_cvref_t<_U0>, tuple>;
876             }
877           else if constexpr (sizeof...(_Elements) < 4)
878             {
879               using _U0 = typename _Nth_type<0, _UTypes...>::type;
880               if constexpr (!is_same_v<remove_cvref_t<_U0>, allocator_arg_t>)
881                 return true;
882               else
883                 {
884                   using _T0 = typename _Nth_type<0, _Elements...>::type;
885                   return is_same_v<remove_cvref_t<_T0>, allocator_arg_t>;
886                 }
887             }
888           return true;
889         }
891       // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
892       // and the single element in Types can be initialized from TUPLE,
893       // or is the same type as tuple_element_t<0, TUPLE>.
894       template<typename _Tuple>
895         static consteval bool
896         __use_other_ctor()
897         {
898           if constexpr (sizeof...(_Elements) != 1)
899             return false;
900           else if constexpr (is_same_v<remove_cvref_t<_Tuple>, tuple>)
901             return true; // Should use a copy/move constructor instead.
902           else
903             {
904               using _Tp = typename _Nth_type<0, _Elements...>::type;
905               if constexpr (is_convertible_v<_Tuple, _Tp>)
906                 return true;
907               else if constexpr (is_constructible_v<_Tp, _Tuple>)
908                 return true;
909             }
910           return false;
911         }
913       template<typename... _Up>
914         static consteval bool
915         __dangles()
916         {
917 #if __has_builtin(__reference_constructs_from_temporary)
918           return (__reference_constructs_from_temporary(_Elements, _Up&&)
919                     || ...);
920 #else
921           return false;
922 #endif
923         }
925 #if __cpp_lib_tuple_like // >= C++23
926       // _GLIBCXX_RESOLVE_LIB_DEFECTS
927       // 4045. tuple can create dangling references from tuple-like
928       template<typename _UTuple>
929         static consteval bool
930         __dangles_from_tuple_like()
931         {
932           return []<size_t... _Is>(index_sequence<_Is...>) {
933             return __dangles<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
934           }(index_sequence_for<_Elements...>{});
935         }
937       template<typename _UTuple>
938         static consteval bool
939         __constructible_from_tuple_like()
940         {
941           return []<size_t... _Is>(index_sequence<_Is...>) {
942             return __constructible<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
943           }(index_sequence_for<_Elements...>{});
944         }
946       template<typename _UTuple>
947         static consteval bool
948         __convertible_from_tuple_like()
949         {
950           return []<size_t... _Is>(index_sequence<_Is...>) {
951             return __convertible<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
952           }(index_sequence_for<_Elements...>{});
953         }
954 #endif // C++23
956     public:
957       constexpr
958       explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
959       tuple()
960       noexcept((is_nothrow_default_constructible_v<_Elements> && ...))
961       requires (is_default_constructible_v<_Elements> && ...)
962       : _Inherited()
963       { }
965       constexpr explicit(!__convertible<const _Elements&...>())
966       tuple(const _Elements&... __elements)
967       noexcept(__nothrow_constructible<const _Elements&...>())
968       requires (__constructible<const _Elements&...>())
969       : _Inherited(__elements...)
970       { }
972       template<typename... _UTypes>
973         requires (__disambiguating_constraint<_UTypes...>())
974           && (__constructible<_UTypes...>())
975           && (!__dangles<_UTypes...>())
976         constexpr explicit(!__convertible<_UTypes...>())
977         tuple(_UTypes&&... __u)
978         noexcept(__nothrow_constructible<_UTypes...>())
979         : _Inherited(std::forward<_UTypes>(__u)...)
980         { }
982       template<typename... _UTypes>
983         requires (__disambiguating_constraint<_UTypes...>())
984           && (__constructible<_UTypes...>())
985           && (__dangles<_UTypes...>())
986         tuple(_UTypes&&...) = delete;
988       constexpr tuple(const tuple&) = default;
990       constexpr tuple(tuple&&) = default;
992       template<typename... _UTypes>
993         requires (__constructible<const _UTypes&...>())
994           && (!__use_other_ctor<const tuple<_UTypes...>&>())
995           && (!__dangles<const _UTypes&...>())
996         constexpr explicit(!__convertible<const _UTypes&...>())
997         tuple(const tuple<_UTypes...>& __u)
998         noexcept(__nothrow_constructible<const _UTypes&...>())
999         : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1000         { }
1002       template<typename... _UTypes>
1003         requires (__constructible<const _UTypes&...>())
1004           && (!__use_other_ctor<const tuple<_UTypes...>&>())
1005           && (__dangles<const _UTypes&...>())
1006         tuple(const tuple<_UTypes...>&) = delete;
1008       template<typename... _UTypes>
1009         requires (__constructible<_UTypes...>())
1010           && (!__use_other_ctor<tuple<_UTypes...>>())
1011           && (!__dangles<_UTypes...>())
1012         constexpr explicit(!__convertible<_UTypes...>())
1013         tuple(tuple<_UTypes...>&& __u)
1014         noexcept(__nothrow_constructible<_UTypes...>())
1015         : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1016         { }
1018       template<typename... _UTypes>
1019         requires (__constructible<_UTypes...>())
1020           && (!__use_other_ctor<tuple<_UTypes...>>())
1021           && (__dangles<_UTypes...>())
1022         tuple(tuple<_UTypes...>&&) = delete;
1024 #if __cpp_lib_ranges_zip // >= C++23
1025       template<typename... _UTypes>
1026         requires (__constructible<_UTypes&...>())
1027           && (!__use_other_ctor<tuple<_UTypes...>&>())
1028           && (!__dangles<_UTypes&...>())
1029         constexpr explicit(!__convertible<_UTypes&...>())
1030         tuple(tuple<_UTypes...>& __u)
1031         noexcept(__nothrow_constructible<_UTypes&...>())
1032         : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1033         { }
1035       template<typename... _UTypes>
1036         requires (__constructible<_UTypes&...>())
1037           && (!__use_other_ctor<tuple<_UTypes...>&>())
1038           && (__dangles<_UTypes&...>())
1039         tuple(tuple<_UTypes...>&) = delete;
1041       template<typename... _UTypes>
1042         requires (__constructible<const _UTypes...>())
1043           && (!__use_other_ctor<const tuple<_UTypes...>>())
1044           && (!__dangles<const _UTypes...>())
1045         constexpr explicit(!__convertible<const _UTypes...>())
1046         tuple(const tuple<_UTypes...>&& __u)
1047         noexcept(__nothrow_constructible<const _UTypes...>())
1048         : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1049         { }
1051       template<typename... _UTypes>
1052         requires (__constructible<const _UTypes...>())
1053           && (!__use_other_ctor<const tuple<_UTypes...>>())
1054           && (__dangles<const _UTypes...>())
1055         tuple(const tuple<_UTypes...>&&) = delete;
1056 #endif // C++23
1058       template<typename _U1, typename _U2>
1059         requires (sizeof...(_Elements) == 2)
1060           && (__constructible<const _U1&, const _U2&>())
1061           && (!__dangles<const _U1&, const _U2&>())
1062         constexpr explicit(!__convertible<const _U1&, const _U2&>())
1063         tuple(const pair<_U1, _U2>& __u)
1064         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1065         : _Inherited(__u.first, __u.second)
1066         { }
1068       template<typename _U1, typename _U2>
1069         requires (sizeof...(_Elements) == 2)
1070           && (__constructible<const _U1&, const _U2&>())
1071           && (__dangles<const _U1&, const _U2&>())
1072         tuple(const pair<_U1, _U2>&) = delete;
1074       template<typename _U1, typename _U2>
1075         requires (sizeof...(_Elements) == 2)
1076           && (__constructible<_U1, _U2>())
1077           && (!__dangles<_U1, _U2>())
1078         constexpr explicit(!__convertible<_U1, _U2>())
1079         tuple(pair<_U1, _U2>&& __u)
1080         noexcept(__nothrow_constructible<_U1, _U2>())
1081         : _Inherited(std::forward<_U1>(__u.first),
1082                      std::forward<_U2>(__u.second))
1083         { }
1085       template<typename _U1, typename _U2>
1086         requires (sizeof...(_Elements) == 2)
1087           && (__constructible<_U1, _U2>())
1088           && (__dangles<_U1, _U2>())
1089         tuple(pair<_U1, _U2>&&) = delete;
1091 #if __cpp_lib_ranges_zip // >= C++23
1092       template<typename _U1, typename _U2>
1093         requires (sizeof...(_Elements) == 2)
1094           && (__constructible<_U1&, _U2&>())
1095           && (!__dangles<_U1&, _U2&>())
1096         constexpr explicit(!__convertible<_U1&, _U2&>())
1097         tuple(pair<_U1, _U2>& __u)
1098         noexcept(__nothrow_constructible<_U1&, _U2&>())
1099         : _Inherited(__u.first, __u.second)
1100         { }
1102       template<typename _U1, typename _U2>
1103         requires (sizeof...(_Elements) == 2)
1104           && (__constructible<_U1&, _U2&>())
1105           && (__dangles<_U1&, _U2&>())
1106         tuple(pair<_U1, _U2>&) = delete;
1108       template<typename _U1, typename _U2>
1109         requires (sizeof...(_Elements) == 2)
1110           && (__constructible<const _U1, const _U2>())
1111           && (!__dangles<const _U1, const _U2>())
1112         constexpr explicit(!__convertible<const _U1, const _U2>())
1113         tuple(const pair<_U1, _U2>&& __u)
1114         noexcept(__nothrow_constructible<const _U1, const _U2>())
1115         : _Inherited(std::forward<const _U1>(__u.first),
1116                      std::forward<const _U2>(__u.second))
1117         { }
1119       template<typename _U1, typename _U2>
1120         requires (sizeof...(_Elements) == 2)
1121           && (__constructible<const _U1, const _U2>())
1122           && (__dangles<const _U1, const _U2>())
1123         tuple(const pair<_U1, _U2>&&) = delete;
1124 #endif // C++23
1126 #if __cpp_lib_tuple_like // >= C++23
1127       template<__eligible_tuple_like<tuple> _UTuple>
1128         requires (__constructible_from_tuple_like<_UTuple>())
1129           && (!__use_other_ctor<_UTuple>())
1130           && (!__dangles_from_tuple_like<_UTuple>())
1131         constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
1132         tuple(_UTuple&& __u)
1133         : _Inherited(__tuple_like_tag_t{},
1134                      std::forward<_UTuple>(__u),
1135                      index_sequence_for<_Elements...>{})
1136         { }
1138       template<__eligible_tuple_like<tuple> _UTuple>
1139         requires (__constructible_from_tuple_like<_UTuple>())
1140           && (!__use_other_ctor<_UTuple>())
1141           && (__dangles_from_tuple_like<_UTuple>())
1142         tuple(_UTuple&&) = delete;
1143 #endif // C++23
1145       // Allocator-extended constructors.
1147       template<typename _Alloc>
1148         constexpr
1149         explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
1150         tuple(allocator_arg_t __tag, const _Alloc& __a)
1151         requires (is_default_constructible_v<_Elements> && ...)
1152         : _Inherited(__tag, __a)
1153         { }
1155       template<typename _Alloc>
1156         constexpr explicit(!__convertible<const _Elements&...>())
1157         tuple(allocator_arg_t __tag, const _Alloc& __a,
1158               const _Elements&... __elements)
1159         requires (__constructible<const _Elements&...>())
1160         : _Inherited(__tag, __a, __elements...)
1161         { }
1163       template<typename _Alloc, typename... _UTypes>
1164         requires (__disambiguating_constraint<_UTypes...>())
1165           && (__constructible<_UTypes...>())
1166           && (!__dangles<_UTypes...>())
1167         constexpr explicit(!__convertible<_UTypes...>())
1168         tuple(allocator_arg_t __tag, const _Alloc& __a, _UTypes&&... __u)
1169         : _Inherited(__tag, __a, std::forward<_UTypes>(__u)...)
1170         { }
1172       template<typename _Alloc, typename... _UTypes>
1173         requires (__disambiguating_constraint<_UTypes...>())
1174           && (__constructible<_UTypes...>())
1175           && (__dangles<_UTypes...>())
1176         tuple(allocator_arg_t, const _Alloc&, _UTypes&&...) = delete;
1178       template<typename _Alloc>
1179         constexpr
1180         tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __u)
1181         : _Inherited(__tag, __a, static_cast<const _Inherited&>(__u))
1182         { }
1184       template<typename _Alloc>
1185         requires (__constructible<_Elements...>())
1186         constexpr
1187         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __u)
1188         : _Inherited(__tag, __a, static_cast<_Inherited&&>(__u))
1189         { }
1191       template<typename _Alloc, typename... _UTypes>
1192         requires (__constructible<const _UTypes&...>())
1193           && (!__use_other_ctor<const tuple<_UTypes...>&>())
1194           && (!__dangles<const _UTypes&...>())
1195         constexpr explicit(!__convertible<const _UTypes&...>())
1196         tuple(allocator_arg_t __tag, const _Alloc& __a,
1197               const tuple<_UTypes...>& __u)
1198         : _Inherited(__tag, __a,
1199                      static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1200         { }
1202       template<typename _Alloc, typename... _UTypes>
1203         requires (__constructible<const _UTypes&...>())
1204           && (!__use_other_ctor<const tuple<_UTypes...>&>())
1205           && (__dangles<const _UTypes&...>())
1206         tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&) = delete;
1208       template<typename _Alloc, typename... _UTypes>
1209         requires (__constructible<_UTypes...>())
1210           && (!__use_other_ctor<tuple<_UTypes...>>())
1211           && (!__dangles<_UTypes...>())
1212         constexpr explicit(!__use_other_ctor<tuple<_UTypes...>>())
1213         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>&& __u)
1214         : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1215         { }
1217       template<typename _Alloc, typename... _UTypes>
1218         requires (__constructible<_UTypes...>())
1219           && (!__use_other_ctor<tuple<_UTypes...>>())
1220           && (__dangles<_UTypes...>())
1221         tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&&) = delete;
1223 #if __cpp_lib_ranges_zip // >= C++23
1224       template<typename _Alloc, typename... _UTypes>
1225         requires (__constructible<_UTypes&...>())
1226           && (!__use_other_ctor<tuple<_UTypes...>&>())
1227           && (!__dangles<_UTypes&...>())
1228         constexpr explicit(!__convertible<_UTypes&...>())
1229         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>& __u)
1230         : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1231         { }
1233       template<typename _Alloc, typename... _UTypes>
1234         requires (__constructible<_UTypes&...>())
1235           && (!__use_other_ctor<tuple<_UTypes...>&>())
1236           && (__dangles<_UTypes&...>())
1237         tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&) = delete;
1239       template<typename _Alloc, typename... _UTypes>
1240         requires (__constructible<const _UTypes...>())
1241           && (!__use_other_ctor<const tuple<_UTypes...>>())
1242           && (!__dangles<const _UTypes...>())
1243         constexpr explicit(!__convertible<const _UTypes...>())
1244         tuple(allocator_arg_t __tag, const _Alloc& __a,
1245               const tuple<_UTypes...>&& __u)
1246         : _Inherited(__tag, __a,
1247                      static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1248         { }
1250       template<typename _Alloc, typename... _UTypes>
1251         requires (__constructible<const _UTypes...>())
1252           && (!__use_other_ctor<const tuple<_UTypes...>>())
1253           && (__dangles<const _UTypes...>())
1254         tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&&) = delete;
1255 #endif // C++23
1257       template<typename _Alloc, typename _U1, typename _U2>
1258         requires (sizeof...(_Elements) == 2)
1259           && (__constructible<const _U1&, const _U2&>())
1260           && (!__dangles<const _U1&, const _U2&>())
1261         constexpr explicit(!__convertible<const _U1&, const _U2&>())
1262         tuple(allocator_arg_t __tag, const _Alloc& __a,
1263               const pair<_U1, _U2>& __u)
1264         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1265         : _Inherited(__tag, __a, __u.first, __u.second)
1266         { }
1268       template<typename _Alloc, typename _U1, typename _U2>
1269         requires (sizeof...(_Elements) == 2)
1270           && (__constructible<const _U1&, const _U2&>())
1271           && (__dangles<const _U1&, const _U2&>())
1272         tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&) = delete;
1274       template<typename _Alloc, typename _U1, typename _U2>
1275         requires (sizeof...(_Elements) == 2)
1276           && (__constructible<_U1, _U2>())
1277           && (!__dangles<_U1, _U2>())
1278         constexpr explicit(!__convertible<_U1, _U2>())
1279         tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __u)
1280         noexcept(__nothrow_constructible<_U1, _U2>())
1281         : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1282         { }
1284       template<typename _Alloc, typename _U1, typename _U2>
1285         requires (sizeof...(_Elements) == 2)
1286           && (__constructible<_U1, _U2>())
1287           && (__dangles<_U1, _U2>())
1288         tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&) = delete;
1290 #if __cpp_lib_ranges_zip // >= C++23
1291       template<typename _Alloc, typename _U1, typename _U2>
1292         requires (sizeof...(_Elements) == 2)
1293           && (__constructible<_U1&, _U2&>())
1294           && (!__dangles<_U1&, _U2&>())
1295         constexpr explicit(!__convertible<_U1&, _U2&>())
1296         tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>& __u)
1297         noexcept(__nothrow_constructible<_U1&, _U2&>())
1298         : _Inherited(__tag, __a, __u.first, __u.second)
1299         { }
1301       template<typename _Alloc, typename _U1, typename _U2>
1302         requires (sizeof...(_Elements) == 2)
1303           && (__constructible<_U1&, _U2&>())
1304           && (__dangles<_U1&, _U2&>())
1305         tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&) = delete;
1307       template<typename _Alloc, typename _U1, typename _U2>
1308         requires (sizeof...(_Elements) == 2)
1309           && (__constructible<const _U1, const _U2>())
1310           && (!__dangles<const _U1, const _U2>())
1311         constexpr explicit(!__convertible<const _U1, const _U2>())
1312         tuple(allocator_arg_t __tag, const _Alloc& __a,
1313         const pair<_U1, _U2>&& __u)
1314         noexcept(__nothrow_constructible<const _U1, const _U2>())
1315         : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1316         { }
1318       template<typename _Alloc, typename _U1, typename _U2>
1319         requires (sizeof...(_Elements) == 2)
1320           && (__constructible<const _U1, const _U2>())
1321           && (__dangles<const _U1, const _U2>())
1322         tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&&) = delete;
1323 #endif // C++23
1325 #if __cpp_lib_tuple_like // >= C++23
1326       template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
1327         requires (__constructible_from_tuple_like<_UTuple>())
1328           && (!__use_other_ctor<_UTuple>())
1329           && (!__dangles_from_tuple_like<_UTuple>())
1330         constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
1331         tuple(allocator_arg_t __tag, const _Alloc& __a, _UTuple&& __u)
1332         : _Inherited(__tuple_like_tag_t{},
1333                      __tag, __a, std::forward<_UTuple>(__u),
1334                      index_sequence_for<_Elements...>{})
1335         { }
1337       template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
1338         requires (__constructible_from_tuple_like<_UTuple>())
1339           && (!__use_other_ctor<_UTuple>())
1340           && (__dangles_from_tuple_like<_UTuple>())
1341         tuple(allocator_arg_t, const _Alloc&, _UTuple&&) = delete;
1342 #endif // C++23
1344 #else // !(concepts && conditional_explicit)
1346       template<bool _Cond>
1347         using _TCC = _TupleConstraints<_Cond, _Elements...>;
1349       // Constraint for non-explicit default constructor
1350       template<bool _Dummy>
1351         using _ImplicitDefaultCtor = __enable_if_t<
1352           _TCC<_Dummy>::__is_implicitly_default_constructible(),
1353           bool>;
1355       // Constraint for explicit default constructor
1356       template<bool _Dummy>
1357         using _ExplicitDefaultCtor = __enable_if_t<
1358           _TCC<_Dummy>::__is_explicitly_default_constructible(),
1359           bool>;
1361       // Constraint for non-explicit constructors
1362       template<bool _Cond, typename... _Args>
1363         using _ImplicitCtor = __enable_if_t<
1364           _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
1365           bool>;
1367       // Constraint for non-explicit constructors
1368       template<bool _Cond, typename... _Args>
1369         using _ExplicitCtor = __enable_if_t<
1370           _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
1371           bool>;
1373       // Condition for noexcept-specifier of a constructor.
1374       template<typename... _UElements>
1375         static constexpr bool __nothrow_constructible()
1376         {
1377           return
1378             __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
1379         }
1381       // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1.
1382       template<typename _Up>
1383         static constexpr bool __valid_args()
1384         {
1385           return sizeof...(_Elements) == 1
1386             && !is_same<tuple, __remove_cvref_t<_Up>>::value;
1387         }
1389       // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1.
1390       template<typename, typename, typename... _Tail>
1391         static constexpr bool __valid_args()
1392         { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); }
1394       /* Constraint for constructors with a tuple<UTypes...> parameter ensures
1395        * that the constructor is only viable when it would not interfere with
1396        * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&).
1397        * Such constructors are only viable if:
1398        * either sizeof...(Types) != 1,
1399        * or (when Types... expands to T and UTypes... expands to U)
1400        * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>,
1401        * and is_same_v<T, U> are all false.
1402        */
1403       template<typename _Tuple, typename = tuple,
1404                typename = __remove_cvref_t<_Tuple>>
1405         struct _UseOtherCtor
1406         : false_type
1407         { };
1408       // If TUPLE is convertible to the single element in *this,
1409       // then TUPLE should match tuple(UTypes&&...) instead.
1410       template<typename _Tuple, typename _Tp, typename _Up>
1411         struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>>
1412         : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>::type
1413         { };
1414       // If TUPLE and *this each have a single element of the same type,
1415       // then TUPLE should match a copy/move constructor instead.
1416       template<typename _Tuple, typename _Tp>
1417         struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>>
1418         : true_type
1419         { };
1421       // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
1422       // and the single element in Types can be initialized from TUPLE,
1423       // or is the same type as tuple_element_t<0, TUPLE>.
1424       template<typename _Tuple>
1425         static constexpr bool __use_other_ctor()
1426         { return _UseOtherCtor<_Tuple>::value; }
1428       /// @cond undocumented
1429 #undef __glibcxx_no_dangling_refs
1430 #if __has_builtin(__reference_constructs_from_temporary) \
1431       && defined _GLIBCXX_DEBUG
1432       // Error if construction from U... would create a dangling ref.
1433 # if __cpp_fold_expressions
1434 #  define __glibcxx_dangling_refs(U) \
1435   (__reference_constructs_from_temporary(_Elements, U) || ...)
1436 # else
1437 #  define __glibcxx_dangling_refs(U) \
1438   __or_<__bool_constant<__reference_constructs_from_temporary(_Elements, U) \
1439        >...>::value
1440 # endif
1441 # define __glibcxx_no_dangling_refs(U) \
1442   static_assert(!__glibcxx_dangling_refs(U), \
1443                 "std::tuple constructor creates a dangling reference")
1444 #else
1445 # define __glibcxx_no_dangling_refs(U)
1446 #endif
1447       /// @endcond
1449     public:
1450       template<typename _Dummy = void,
1451                _ImplicitDefaultCtor<is_void<_Dummy>::value> = true>
1452         constexpr
1453         tuple()
1454         noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1455         : _Inherited() { }
1457       template<typename _Dummy = void,
1458                _ExplicitDefaultCtor<is_void<_Dummy>::value> = false>
1459         explicit constexpr
1460         tuple()
1461         noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1462         : _Inherited() { }
1464       template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1465                _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1466         constexpr
1467         tuple(const _Elements&... __elements)
1468         noexcept(__nothrow_constructible<const _Elements&...>())
1469         : _Inherited(__elements...) { }
1471       template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1472                _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1473         explicit constexpr
1474         tuple(const _Elements&... __elements)
1475         noexcept(__nothrow_constructible<const _Elements&...>())
1476         : _Inherited(__elements...) { }
1478       template<typename... _UElements,
1479                bool _Valid = __valid_args<_UElements...>(),
1480                _ImplicitCtor<_Valid, _UElements...> = true>
1481         constexpr
1482         tuple(_UElements&&... __elements)
1483         noexcept(__nothrow_constructible<_UElements...>())
1484         : _Inherited(std::forward<_UElements>(__elements)...)
1485         { __glibcxx_no_dangling_refs(_UElements&&); }
1487       template<typename... _UElements,
1488                bool _Valid = __valid_args<_UElements...>(),
1489                _ExplicitCtor<_Valid, _UElements...> = false>
1490         explicit constexpr
1491         tuple(_UElements&&... __elements)
1492         noexcept(__nothrow_constructible<_UElements...>())
1493         : _Inherited(std::forward<_UElements>(__elements)...)
1494         { __glibcxx_no_dangling_refs(_UElements&&); }
1496       constexpr tuple(const tuple&) = default;
1498       constexpr tuple(tuple&&) = default;
1500       template<typename... _UElements,
1501                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1502                            && !__use_other_ctor<const tuple<_UElements...>&>(),
1503                _ImplicitCtor<_Valid, const _UElements&...> = true>
1504         constexpr
1505         tuple(const tuple<_UElements...>& __in)
1506         noexcept(__nothrow_constructible<const _UElements&...>())
1507         : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1508         { __glibcxx_no_dangling_refs(const _UElements&); }
1510       template<typename... _UElements,
1511                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1512                            && !__use_other_ctor<const tuple<_UElements...>&>(),
1513                _ExplicitCtor<_Valid, const _UElements&...> = false>
1514         explicit constexpr
1515         tuple(const tuple<_UElements...>& __in)
1516         noexcept(__nothrow_constructible<const _UElements&...>())
1517         : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1518         { __glibcxx_no_dangling_refs(const _UElements&); }
1520       template<typename... _UElements,
1521                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1522                              && !__use_other_ctor<tuple<_UElements...>&&>(),
1523                _ImplicitCtor<_Valid, _UElements...> = true>
1524         constexpr
1525         tuple(tuple<_UElements...>&& __in)
1526         noexcept(__nothrow_constructible<_UElements...>())
1527         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1528         { __glibcxx_no_dangling_refs(_UElements&&); }
1530       template<typename... _UElements,
1531                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1532                              && !__use_other_ctor<tuple<_UElements...>&&>(),
1533                _ExplicitCtor<_Valid, _UElements...> = false>
1534         explicit constexpr
1535         tuple(tuple<_UElements...>&& __in)
1536         noexcept(__nothrow_constructible<_UElements...>())
1537         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1538         { __glibcxx_no_dangling_refs(_UElements&&); }
1540       // Allocator-extended constructors.
1542       template<typename _Alloc,
1543                _ImplicitDefaultCtor<is_object<_Alloc>::value> = true>
1544         _GLIBCXX20_CONSTEXPR
1545         tuple(allocator_arg_t __tag, const _Alloc& __a)
1546         : _Inherited(__tag, __a) { }
1548       template<typename _Alloc,
1549                _ExplicitDefaultCtor<is_object<_Alloc>::value> = false>
1550         _GLIBCXX20_CONSTEXPR
1551         explicit
1552         tuple(allocator_arg_t __tag, const _Alloc& __a)
1553         : _Inherited(__tag, __a) { }
1555       template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1556                _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1557         _GLIBCXX20_CONSTEXPR
1558         tuple(allocator_arg_t __tag, const _Alloc& __a,
1559               const _Elements&... __elements)
1560         : _Inherited(__tag, __a, __elements...) { }
1562       template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1563                _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1564         _GLIBCXX20_CONSTEXPR
1565         explicit
1566         tuple(allocator_arg_t __tag, const _Alloc& __a,
1567               const _Elements&... __elements)
1568         : _Inherited(__tag, __a, __elements...) { }
1570       template<typename _Alloc, typename... _UElements,
1571                bool _Valid = __valid_args<_UElements...>(),
1572                _ImplicitCtor<_Valid, _UElements...> = true>
1573         _GLIBCXX20_CONSTEXPR
1574         tuple(allocator_arg_t __tag, const _Alloc& __a,
1575               _UElements&&... __elements)
1576         : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1577         { __glibcxx_no_dangling_refs(_UElements&&); }
1579       template<typename _Alloc, typename... _UElements,
1580                  bool _Valid = __valid_args<_UElements...>(),
1581                _ExplicitCtor<_Valid, _UElements...> = false>
1582         _GLIBCXX20_CONSTEXPR
1583         explicit
1584         tuple(allocator_arg_t __tag, const _Alloc& __a,
1585               _UElements&&... __elements)
1586         : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1587         { __glibcxx_no_dangling_refs(_UElements&&); }
1589       template<typename _Alloc>
1590         _GLIBCXX20_CONSTEXPR
1591         tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1592         : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1594       template<typename _Alloc>
1595         _GLIBCXX20_CONSTEXPR
1596         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1597         : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1599       template<typename _Alloc, typename... _UElements,
1600                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1601                              && !__use_other_ctor<const tuple<_UElements...>&>(),
1602                _ImplicitCtor<_Valid, const _UElements&...> = true>
1603         _GLIBCXX20_CONSTEXPR
1604         tuple(allocator_arg_t __tag, const _Alloc& __a,
1605               const tuple<_UElements...>& __in)
1606         : _Inherited(__tag, __a,
1607                      static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1608         { __glibcxx_no_dangling_refs(const _UElements&); }
1610       template<typename _Alloc, typename... _UElements,
1611                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1612                              && !__use_other_ctor<const tuple<_UElements...>&>(),
1613                _ExplicitCtor<_Valid, const _UElements&...> = false>
1614         _GLIBCXX20_CONSTEXPR
1615         explicit
1616         tuple(allocator_arg_t __tag, const _Alloc& __a,
1617               const tuple<_UElements...>& __in)
1618         : _Inherited(__tag, __a,
1619                      static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1620         { __glibcxx_no_dangling_refs(const _UElements&); }
1622       template<typename _Alloc, typename... _UElements,
1623                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1624                              && !__use_other_ctor<tuple<_UElements...>&&>(),
1625                _ImplicitCtor<_Valid, _UElements...> = true>
1626         _GLIBCXX20_CONSTEXPR
1627         tuple(allocator_arg_t __tag, const _Alloc& __a,
1628               tuple<_UElements...>&& __in)
1629         : _Inherited(__tag, __a,
1630                      static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1631         { __glibcxx_no_dangling_refs(_UElements&&); }
1633       template<typename _Alloc, typename... _UElements,
1634                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1635                              && !__use_other_ctor<tuple<_UElements...>&&>(),
1636                _ExplicitCtor<_Valid, _UElements...> = false>
1637         _GLIBCXX20_CONSTEXPR
1638         explicit
1639         tuple(allocator_arg_t __tag, const _Alloc& __a,
1640               tuple<_UElements...>&& __in)
1641         : _Inherited(__tag, __a,
1642                      static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1643         { __glibcxx_no_dangling_refs(_UElements&&); }
1644 #endif // concepts && conditional_explicit
1646       // tuple assignment
1648 #if __cpp_concepts && __cpp_consteval // >= C++20
1649     private:
1650       template<typename... _UTypes>
1651         static consteval bool
1652         __assignable()
1653         {
1654           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1655             return __and_v<is_assignable<_Elements&, _UTypes>...>;
1656           else
1657             return false;
1658         }
1660       template<typename... _UTypes>
1661         static consteval bool
1662         __nothrow_assignable()
1663         {
1664           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1665             return __and_v<is_nothrow_assignable<_Elements&, _UTypes>...>;
1666           else
1667             return false;
1668         }
1670 #if __cpp_lib_ranges_zip // >= C++23
1671       template<typename... _UTypes>
1672         static consteval bool
1673         __const_assignable()
1674         {
1675           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1676             return __and_v<is_assignable<const _Elements&, _UTypes>...>;
1677           else
1678             return false;
1679         }
1680 #endif // C++23
1682 #if __cpp_lib_tuple_like // >= C++23
1683       template<typename _UTuple>
1684         static consteval bool
1685         __assignable_from_tuple_like()
1686         {
1687           return []<size_t... _Is>(index_sequence<_Is...>) {
1688             return __assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1689           }(index_sequence_for<_Elements...>{});
1690         }
1692       template<typename _UTuple>
1693         static consteval bool
1694         __const_assignable_from_tuple_like()
1695         {
1696           return []<size_t... _Is>(index_sequence<_Is...>) {
1697             return __const_assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1698           }(index_sequence_for<_Elements...>{});
1699         }
1700 #endif // C++23
1702     public:
1704       tuple& operator=(const tuple& __u) = delete;
1706       constexpr tuple&
1707       operator=(const tuple& __u)
1708       noexcept(__nothrow_assignable<const _Elements&...>())
1709       requires (__assignable<const _Elements&...>())
1710       {
1711         this->_M_assign(__u);
1712         return *this;
1713       }
1715       constexpr tuple&
1716       operator=(tuple&& __u)
1717       noexcept(__nothrow_assignable<_Elements...>())
1718       requires (__assignable<_Elements...>())
1719       {
1720         this->_M_assign(std::move(__u));
1721         return *this;
1722       }
1724       template<typename... _UTypes>
1725         requires (__assignable<const _UTypes&...>())
1726         constexpr tuple&
1727         operator=(const tuple<_UTypes...>& __u)
1728         noexcept(__nothrow_assignable<const _UTypes&...>())
1729         {
1730           this->_M_assign(__u);
1731           return *this;
1732         }
1734       template<typename... _UTypes>
1735         requires (__assignable<_UTypes...>())
1736         constexpr tuple&
1737         operator=(tuple<_UTypes...>&& __u)
1738         noexcept(__nothrow_assignable<_UTypes...>())
1739         {
1740           this->_M_assign(std::move(__u));
1741           return *this;
1742         }
1744 #if __cpp_lib_ranges_zip // >= C++23
1745       constexpr const tuple&
1746       operator=(const tuple& __u) const
1747       requires (__const_assignable<const _Elements&...>())
1748       {
1749         this->_M_assign(__u);
1750         return *this;
1751       }
1753       constexpr const tuple&
1754       operator=(tuple&& __u) const
1755       requires (__const_assignable<_Elements...>())
1756       {
1757         this->_M_assign(std::move(__u));
1758         return *this;
1759       }
1761       template<typename... _UTypes>
1762         constexpr const tuple&
1763         operator=(const tuple<_UTypes...>& __u) const
1764         requires (__const_assignable<const _UTypes&...>())
1765         {
1766           this->_M_assign(__u);
1767           return *this;
1768         }
1770       template<typename... _UTypes>
1771         constexpr const tuple&
1772         operator=(tuple<_UTypes...>&& __u) const
1773         requires (__const_assignable<_UTypes...>())
1774         {
1775           this->_M_assign(std::move(__u));
1776           return *this;
1777         }
1778 #endif // C++23
1780       template<typename _U1, typename _U2>
1781         requires (__assignable<const _U1&, const _U2&>())
1782         constexpr tuple&
1783         operator=(const pair<_U1, _U2>& __u)
1784         noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1785         {
1786           this->_M_head(*this) = __u.first;
1787           this->_M_tail(*this)._M_head(*this) = __u.second;
1788           return *this;
1789         }
1791       template<typename _U1, typename _U2>
1792         requires (__assignable<_U1, _U2>())
1793         constexpr tuple&
1794         operator=(pair<_U1, _U2>&& __u)
1795         noexcept(__nothrow_assignable<_U1, _U2>())
1796         {
1797           this->_M_head(*this) = std::forward<_U1>(__u.first);
1798           this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1799           return *this;
1800         }
1802 #if __cpp_lib_ranges_zip // >= C++23
1803       template<typename _U1, typename _U2>
1804         requires (__const_assignable<const _U1&, const _U2>())
1805         constexpr const tuple&
1806         operator=(const pair<_U1, _U2>& __u) const
1807         {
1808           this->_M_head(*this) = __u.first;
1809           this->_M_tail(*this)._M_head(*this) = __u.second;
1810           return *this;
1811         }
1813       template<typename _U1, typename _U2>
1814         requires (__const_assignable<_U1, _U2>())
1815         constexpr const tuple&
1816         operator=(pair<_U1, _U2>&& __u) const
1817         {
1818           this->_M_head(*this) = std::forward<_U1>(__u.first);
1819           this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1820           return *this;
1821         }
1822 #endif // C++23
1824 #if __cpp_lib_tuple_like // >= C++23
1825       template<__eligible_tuple_like<tuple> _UTuple>
1826         requires (__assignable_from_tuple_like<_UTuple>())
1827         constexpr tuple&
1828         operator=(_UTuple&& __u)
1829         {
1830           this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1831           return *this;
1832         }
1834       template<__eligible_tuple_like<tuple> _UTuple>
1835         requires (__const_assignable_from_tuple_like<_UTuple>())
1836         constexpr const tuple&
1837         operator=(_UTuple&& __u) const
1838         {
1839           this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1840           return *this;
1841         }
1843       template<__tuple_like _UTuple>
1844         requires (!__is_tuple_v<_UTuple>)
1845         friend constexpr bool
1846         operator== [[nodiscard]] (const tuple& __t, const _UTuple& __u)
1847         {
1848           static_assert(sizeof...(_Elements) == tuple_size_v<_UTuple>,
1849               "tuple objects can only be compared if they have equal sizes.");
1850           return [&]<size_t... _Is>(index_sequence<_Is...>) {
1851             return (bool(std::get<_Is>(__t) == std::get<_Is>(__u))
1852                     && ...);
1853           }(index_sequence_for<_Elements...>{});
1854         }
1856       template<__tuple_like _UTuple,
1857                typename = make_index_sequence<tuple_size_v<_UTuple>>>
1858         struct __tuple_like_common_comparison_category;
1860       template<__tuple_like _UTuple, size_t... _Is>
1861         requires requires
1862           { typename void_t<__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>; }
1863         struct __tuple_like_common_comparison_category<_UTuple, index_sequence<_Is...>>
1864         {
1865           using type = common_comparison_category_t
1866             <__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>;
1867         };
1869       template<__tuple_like _UTuple>
1870         requires (!__is_tuple_v<_UTuple>)
1871         friend constexpr typename __tuple_like_common_comparison_category<_UTuple>::type
1872         operator<=>(const tuple& __t, const _UTuple& __u)
1873         {
1874           using _Cat = typename __tuple_like_common_comparison_category<_UTuple>::type;
1875           return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Elements...>());
1876         }
1877 #endif // C++23
1879 #else // ! (concepts && consteval)
1881     private:
1882       template<typename... _UElements>
1883         static constexpr
1884         __enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
1885         __assignable()
1886         { return __and_<is_assignable<_Elements&, _UElements>...>::value; }
1888       // Condition for noexcept-specifier of an assignment operator.
1889       template<typename... _UElements>
1890         static constexpr bool __nothrow_assignable()
1891         {
1892           return
1893             __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
1894         }
1896     public:
1898       _GLIBCXX20_CONSTEXPR
1899       tuple&
1900       operator=(__conditional_t<__assignable<const _Elements&...>(),
1901                                 const tuple&,
1902                                 const __nonesuch&> __in)
1903       noexcept(__nothrow_assignable<const _Elements&...>())
1904       {
1905         this->_M_assign(__in);
1906         return *this;
1907       }
1909       _GLIBCXX20_CONSTEXPR
1910       tuple&
1911       operator=(__conditional_t<__assignable<_Elements...>(),
1912                                 tuple&&,
1913                                 __nonesuch&&> __in)
1914       noexcept(__nothrow_assignable<_Elements...>())
1915       {
1916         this->_M_assign(std::move(__in));
1917         return *this;
1918       }
1920       template<typename... _UElements>
1921         _GLIBCXX20_CONSTEXPR
1922         __enable_if_t<__assignable<const _UElements&...>(), tuple&>
1923         operator=(const tuple<_UElements...>& __in)
1924         noexcept(__nothrow_assignable<const _UElements&...>())
1925         {
1926           this->_M_assign(__in);
1927           return *this;
1928         }
1930       template<typename... _UElements>
1931         _GLIBCXX20_CONSTEXPR
1932         __enable_if_t<__assignable<_UElements...>(), tuple&>
1933         operator=(tuple<_UElements...>&& __in)
1934         noexcept(__nothrow_assignable<_UElements...>())
1935         {
1936           this->_M_assign(std::move(__in));
1937           return *this;
1938         }
1939 #endif // concepts && consteval
1941       // tuple swap
1942       _GLIBCXX20_CONSTEXPR
1943       void
1944       swap(tuple& __in)
1945       noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
1946       { _Inherited::_M_swap(__in); }
1948 #if __cpp_lib_ranges_zip // >= C++23
1949       // As an extension, we constrain the const swap member function in order
1950       // to continue accepting explicit instantiation of tuples whose elements
1951       // are not all const swappable.  Without this constraint, such an
1952       // explicit instantiation would also instantiate the ill-formed body of
1953       // this function and yield a hard error.  This constraint shouldn't
1954       // affect the behavior of valid programs.
1955       constexpr void
1956       swap(const tuple& __in) const
1957       noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
1958       requires (is_swappable_v<const _Elements> && ...)
1959       { _Inherited::_M_swap(__in); }
1960 #endif // C++23
1961     };
1963 #if __cpp_deduction_guides >= 201606
1964   template<typename... _UTypes>
1965     tuple(_UTypes...) -> tuple<_UTypes...>;
1966   template<typename _T1, typename _T2>
1967     tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
1968   template<typename _Alloc, typename... _UTypes>
1969     tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
1970   template<typename _Alloc, typename _T1, typename _T2>
1971     tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
1972   template<typename _Alloc, typename... _UTypes>
1973     tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
1974 #endif
1976   // Explicit specialization, zero-element tuple.
1977   template<>
1978     class tuple<>
1979     {
1980     public:
1981       _GLIBCXX20_CONSTEXPR
1982       void swap(tuple&) noexcept { /* no-op */ }
1983 #if __cpp_lib_ranges_zip // >= C++23
1984       constexpr void swap(const tuple&) const noexcept { /* no-op */ }
1985 #endif
1986       // We need the default since we're going to define no-op
1987       // allocator constructors.
1988       tuple() = default;
1989       // No-op allocator constructors.
1990       template<typename _Alloc>
1991         _GLIBCXX20_CONSTEXPR
1992         tuple(allocator_arg_t, const _Alloc&) noexcept { }
1993       template<typename _Alloc>
1994         _GLIBCXX20_CONSTEXPR
1995         tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
1996     };
1998 #if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20
1999   /// Partial specialization, 2-element tuple.
2000   /// Includes construction and assignment from a pair.
2001   template<typename _T1, typename _T2>
2002     class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
2003     {
2004       typedef _Tuple_impl<0, _T1, _T2> _Inherited;
2006       // Constraint for non-explicit default constructor
2007       template<bool _Dummy, typename _U1, typename _U2>
2008         using _ImplicitDefaultCtor = __enable_if_t<
2009           _TupleConstraints<_Dummy, _U1, _U2>::
2010             __is_implicitly_default_constructible(),
2011           bool>;
2013       // Constraint for explicit default constructor
2014       template<bool _Dummy, typename _U1, typename _U2>
2015         using _ExplicitDefaultCtor = __enable_if_t<
2016           _TupleConstraints<_Dummy, _U1, _U2>::
2017             __is_explicitly_default_constructible(),
2018           bool>;
2020       template<bool _Dummy>
2021         using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
2023       // Constraint for non-explicit constructors
2024       template<bool _Cond, typename _U1, typename _U2>
2025         using _ImplicitCtor = __enable_if_t<
2026           _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
2027           bool>;
2029       // Constraint for non-explicit constructors
2030       template<bool _Cond, typename _U1, typename _U2>
2031         using _ExplicitCtor = __enable_if_t<
2032           _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
2033           bool>;
2035       template<typename _U1, typename _U2>
2036         static constexpr bool __assignable()
2037         {
2038           return __and_<is_assignable<_T1&, _U1>,
2039                         is_assignable<_T2&, _U2>>::value;
2040         }
2042       template<typename _U1, typename _U2>
2043         static constexpr bool __nothrow_assignable()
2044         {
2045           return __and_<is_nothrow_assignable<_T1&, _U1>,
2046                         is_nothrow_assignable<_T2&, _U2>>::value;
2047         }
2049       template<typename _U1, typename _U2>
2050         static constexpr bool __nothrow_constructible()
2051         {
2052           return __and_<is_nothrow_constructible<_T1, _U1>,
2053                             is_nothrow_constructible<_T2, _U2>>::value;
2054         }
2056       static constexpr bool __nothrow_default_constructible()
2057       {
2058         return __and_<is_nothrow_default_constructible<_T1>,
2059                       is_nothrow_default_constructible<_T2>>::value;
2060       }
2062       template<typename _U1>
2063         static constexpr bool __is_alloc_arg()
2064         { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
2066       /// @cond undocumented
2067 #undef __glibcxx_no_dangling_refs
2068       // Error if construction from _U1 and _U2 would create a dangling ref.
2069 #if __has_builtin(__reference_constructs_from_temporary) \
2070       && defined _GLIBCXX_DEBUG
2071 # define __glibcxx_no_dangling_refs(_U1, _U2) \
2072   static_assert(!__reference_constructs_from_temporary(_T1, _U1) \
2073                && !__reference_constructs_from_temporary(_T2, _U2), \
2074                 "std::tuple constructor creates a dangling reference")
2075 #else
2076 # define __glibcxx_no_dangling_refs(_U1, _U2)
2077 #endif
2078       /// @endcond
2080     public:
2081       template<bool _Dummy = true,
2082                _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
2083         constexpr
2084         tuple()
2085         noexcept(__nothrow_default_constructible())
2086         : _Inherited() { }
2088       template<bool _Dummy = true,
2089                _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
2090         explicit constexpr
2091         tuple()
2092         noexcept(__nothrow_default_constructible())
2093         : _Inherited() { }
2095       template<bool _Dummy = true,
2096                _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2097         constexpr
2098         tuple(const _T1& __a1, const _T2& __a2)
2099         noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2100         : _Inherited(__a1, __a2) { }
2102       template<bool _Dummy = true,
2103                _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2104         explicit constexpr
2105         tuple(const _T1& __a1, const _T2& __a2)
2106         noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2107         : _Inherited(__a1, __a2) { }
2109       template<typename _U1, typename _U2,
2110                _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
2111         constexpr
2112         tuple(_U1&& __a1, _U2&& __a2)
2113         noexcept(__nothrow_constructible<_U1, _U2>())
2114         : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2115         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2117       template<typename _U1, typename _U2,
2118                _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
2119         explicit constexpr
2120         tuple(_U1&& __a1, _U2&& __a2)
2121         noexcept(__nothrow_constructible<_U1, _U2>())
2122         : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2123         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2125       constexpr tuple(const tuple&) = default;
2127       constexpr tuple(tuple&&) = default;
2129       template<typename _U1, typename _U2,
2130                _ImplicitCtor<true, const _U1&, const _U2&> = true>
2131         constexpr
2132         tuple(const tuple<_U1, _U2>& __in)
2133         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2134         : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2135         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2137       template<typename _U1, typename _U2,
2138                _ExplicitCtor<true, const _U1&, const _U2&> = false>
2139         explicit constexpr
2140         tuple(const tuple<_U1, _U2>& __in)
2141         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2142         : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2143         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2145       template<typename _U1, typename _U2,
2146                _ImplicitCtor<true, _U1, _U2> = true>
2147         constexpr
2148         tuple(tuple<_U1, _U2>&& __in)
2149         noexcept(__nothrow_constructible<_U1, _U2>())
2150         : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2151         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2153       template<typename _U1, typename _U2,
2154                _ExplicitCtor<true, _U1, _U2> = false>
2155         explicit constexpr
2156         tuple(tuple<_U1, _U2>&& __in)
2157         noexcept(__nothrow_constructible<_U1, _U2>())
2158         : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2159         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2161       template<typename _U1, typename _U2,
2162                _ImplicitCtor<true, const _U1&, const _U2&> = true>
2163         constexpr
2164         tuple(const pair<_U1, _U2>& __in)
2165         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2166         : _Inherited(__in.first, __in.second)
2167         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2169       template<typename _U1, typename _U2,
2170                _ExplicitCtor<true, const _U1&, const _U2&> = false>
2171         explicit constexpr
2172         tuple(const pair<_U1, _U2>& __in)
2173         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2174         : _Inherited(__in.first, __in.second)
2175         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2177       template<typename _U1, typename _U2,
2178                _ImplicitCtor<true, _U1, _U2> = true>
2179         constexpr
2180         tuple(pair<_U1, _U2>&& __in)
2181         noexcept(__nothrow_constructible<_U1, _U2>())
2182         : _Inherited(std::forward<_U1>(__in.first),
2183                      std::forward<_U2>(__in.second))
2184         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2186       template<typename _U1, typename _U2,
2187                _ExplicitCtor<true, _U1, _U2> = false>
2188         explicit constexpr
2189         tuple(pair<_U1, _U2>&& __in)
2190         noexcept(__nothrow_constructible<_U1, _U2>())
2191         : _Inherited(std::forward<_U1>(__in.first),
2192                      std::forward<_U2>(__in.second))
2193         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2195       // Allocator-extended constructors.
2197       template<typename _Alloc,
2198                _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
2199         _GLIBCXX20_CONSTEXPR
2200         tuple(allocator_arg_t __tag, const _Alloc& __a)
2201         : _Inherited(__tag, __a) { }
2203       template<typename _Alloc,
2204                _ExplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = false>
2205         _GLIBCXX20_CONSTEXPR
2206         explicit
2207         tuple(allocator_arg_t __tag, const _Alloc& __a)
2208         : _Inherited(__tag, __a) { }
2210       template<typename _Alloc, bool _Dummy = true,
2211                _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2212         _GLIBCXX20_CONSTEXPR
2213         tuple(allocator_arg_t __tag, const _Alloc& __a,
2214               const _T1& __a1, const _T2& __a2)
2215         : _Inherited(__tag, __a, __a1, __a2) { }
2217       template<typename _Alloc, bool _Dummy = true,
2218                _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2219         explicit
2220         _GLIBCXX20_CONSTEXPR
2221         tuple(allocator_arg_t __tag, const _Alloc& __a,
2222               const _T1& __a1, const _T2& __a2)
2223         : _Inherited(__tag, __a, __a1, __a2) { }
2225       template<typename _Alloc, typename _U1, typename _U2,
2226                _ImplicitCtor<true, _U1, _U2> = true>
2227         _GLIBCXX20_CONSTEXPR
2228         tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
2229         : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2230                      std::forward<_U2>(__a2))
2231         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2233       template<typename _Alloc, typename _U1, typename _U2,
2234                _ExplicitCtor<true, _U1, _U2> = false>
2235         explicit
2236         _GLIBCXX20_CONSTEXPR
2237         tuple(allocator_arg_t __tag, const _Alloc& __a,
2238               _U1&& __a1, _U2&& __a2)
2239         : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2240                      std::forward<_U2>(__a2))
2241         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2243       template<typename _Alloc>
2244         _GLIBCXX20_CONSTEXPR
2245         tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
2246         : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
2248       template<typename _Alloc>
2249         _GLIBCXX20_CONSTEXPR
2250         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
2251         : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
2253       template<typename _Alloc, typename _U1, typename _U2,
2254                _ImplicitCtor<true, const _U1&, const _U2&> = true>
2255         _GLIBCXX20_CONSTEXPR
2256         tuple(allocator_arg_t __tag, const _Alloc& __a,
2257               const tuple<_U1, _U2>& __in)
2258         : _Inherited(__tag, __a,
2259                      static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2260         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2262       template<typename _Alloc, typename _U1, typename _U2,
2263                _ExplicitCtor<true, const _U1&, const _U2&> = false>
2264         explicit
2265         _GLIBCXX20_CONSTEXPR
2266         tuple(allocator_arg_t __tag, const _Alloc& __a,
2267               const tuple<_U1, _U2>& __in)
2268         : _Inherited(__tag, __a,
2269                      static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2270         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2272       template<typename _Alloc, typename _U1, typename _U2,
2273                _ImplicitCtor<true, _U1, _U2> = true>
2274         _GLIBCXX20_CONSTEXPR
2275         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2276         : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2277         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2279       template<typename _Alloc, typename _U1, typename _U2,
2280                _ExplicitCtor<true, _U1, _U2> = false>
2281         explicit
2282         _GLIBCXX20_CONSTEXPR
2283         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2284         : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2285         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2287       template<typename _Alloc, typename _U1, typename _U2,
2288                _ImplicitCtor<true, const _U1&, const _U2&> = true>
2289         _GLIBCXX20_CONSTEXPR
2290         tuple(allocator_arg_t __tag, const _Alloc& __a,
2291               const pair<_U1, _U2>& __in)
2292         : _Inherited(__tag, __a, __in.first, __in.second)
2293         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2295       template<typename _Alloc, typename _U1, typename _U2,
2296                _ExplicitCtor<true, const _U1&, const _U2&> = false>
2297         explicit
2298         _GLIBCXX20_CONSTEXPR
2299         tuple(allocator_arg_t __tag, const _Alloc& __a,
2300               const pair<_U1, _U2>& __in)
2301         : _Inherited(__tag, __a, __in.first, __in.second)
2302         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2304       template<typename _Alloc, typename _U1, typename _U2,
2305                _ImplicitCtor<true, _U1, _U2> = true>
2306         _GLIBCXX20_CONSTEXPR
2307         tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2308         : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2309                      std::forward<_U2>(__in.second))
2310         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2312       template<typename _Alloc, typename _U1, typename _U2,
2313                _ExplicitCtor<true, _U1, _U2> = false>
2314         explicit
2315         _GLIBCXX20_CONSTEXPR
2316         tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2317         : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2318                      std::forward<_U2>(__in.second))
2319         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2321       // Tuple assignment.
2323       _GLIBCXX20_CONSTEXPR
2324       tuple&
2325       operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
2326                                 const tuple&,
2327                                 const __nonesuch&> __in)
2328       noexcept(__nothrow_assignable<const _T1&, const _T2&>())
2329       {
2330         this->_M_assign(__in);
2331         return *this;
2332       }
2334       _GLIBCXX20_CONSTEXPR
2335       tuple&
2336       operator=(__conditional_t<__assignable<_T1, _T2>(),
2337                                 tuple&&,
2338                                 __nonesuch&&> __in)
2339       noexcept(__nothrow_assignable<_T1, _T2>())
2340       {
2341         this->_M_assign(std::move(__in));
2342         return *this;
2343       }
2345       template<typename _U1, typename _U2>
2346         _GLIBCXX20_CONSTEXPR
2347         __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2348         operator=(const tuple<_U1, _U2>& __in)
2349         noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2350         {
2351           this->_M_assign(__in);
2352           return *this;
2353         }
2355       template<typename _U1, typename _U2>
2356         _GLIBCXX20_CONSTEXPR
2357         __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2358         operator=(tuple<_U1, _U2>&& __in)
2359         noexcept(__nothrow_assignable<_U1, _U2>())
2360         {
2361           this->_M_assign(std::move(__in));
2362           return *this;
2363         }
2365       template<typename _U1, typename _U2>
2366         _GLIBCXX20_CONSTEXPR
2367         __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2368         operator=(const pair<_U1, _U2>& __in)
2369         noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2370         {
2371           this->_M_head(*this) = __in.first;
2372           this->_M_tail(*this)._M_head(*this) = __in.second;
2373           return *this;
2374         }
2376       template<typename _U1, typename _U2>
2377         _GLIBCXX20_CONSTEXPR
2378         __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2379         operator=(pair<_U1, _U2>&& __in)
2380         noexcept(__nothrow_assignable<_U1, _U2>())
2381         {
2382           this->_M_head(*this) = std::forward<_U1>(__in.first);
2383           this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
2384           return *this;
2385         }
2387       _GLIBCXX20_CONSTEXPR
2388       void
2389       swap(tuple& __in)
2390       noexcept(__and_<__is_nothrow_swappable<_T1>,
2391                       __is_nothrow_swappable<_T2>>::value)
2392       { _Inherited::_M_swap(__in); }
2393     };
2394 #endif // concepts && conditional_explicit
2396   /// class tuple_size
2397   template<typename... _Elements>
2398     struct tuple_size<tuple<_Elements...>>
2399     : public integral_constant<size_t, sizeof...(_Elements)> { };
2401 #if __cplusplus >= 201703L
2402   template<typename... _Types>
2403     inline constexpr size_t tuple_size_v<tuple<_Types...>>
2404       = sizeof...(_Types);
2406   template<typename... _Types>
2407     inline constexpr size_t tuple_size_v<const tuple<_Types...>>
2408       = sizeof...(_Types);
2409 #endif
2411   /// Trait to get the Ith element type from a tuple.
2412   template<size_t __i, typename... _Types>
2413     struct tuple_element<__i, tuple<_Types...>>
2414     {
2415       static_assert(__i < sizeof...(_Types), "tuple index must be in range");
2417       using type = typename _Nth_type<__i, _Types...>::type;
2418     };
2420   template<size_t __i, typename _Head, typename... _Tail>
2421     constexpr _Head&
2422     __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2423     { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2425   template<size_t __i, typename _Head, typename... _Tail>
2426     constexpr const _Head&
2427     __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2428     { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2430   // Deleted overload to improve diagnostics for invalid indices
2431   template<size_t __i, typename... _Types>
2432     __enable_if_t<(__i >= sizeof...(_Types))>
2433     __get_helper(const tuple<_Types...>&) = delete;
2435   /// Return a reference to the ith element of a tuple.
2436   template<size_t __i, typename... _Elements>
2437     constexpr __tuple_element_t<__i, tuple<_Elements...>>&
2438     get(tuple<_Elements...>& __t) noexcept
2439     { return std::__get_helper<__i>(__t); }
2441   /// Return a const reference to the ith element of a const tuple.
2442   template<size_t __i, typename... _Elements>
2443     constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
2444     get(const tuple<_Elements...>& __t) noexcept
2445     { return std::__get_helper<__i>(__t); }
2447   /// Return an rvalue reference to the ith element of a tuple rvalue.
2448   template<size_t __i, typename... _Elements>
2449     constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
2450     get(tuple<_Elements...>&& __t) noexcept
2451     {
2452       typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2453       return std::forward<__element_type>(std::__get_helper<__i>(__t));
2454     }
2456   /// Return a const rvalue reference to the ith element of a const tuple rvalue.
2457   template<size_t __i, typename... _Elements>
2458     constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
2459     get(const tuple<_Elements...>&& __t) noexcept
2460     {
2461       typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2462       return std::forward<const __element_type>(std::__get_helper<__i>(__t));
2463     }
2465   /// @cond undocumented
2466   // Deleted overload chosen for invalid indices.
2467   template<size_t __i, typename... _Elements>
2468     constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
2469     get(const tuple<_Elements...>&) = delete;
2470   /// @endcond
2472 #ifdef __cpp_lib_tuples_by_type // C++ >= 14
2473   /// Return a reference to the unique element of type _Tp of a tuple.
2474   template <typename _Tp, typename... _Types>
2475     constexpr _Tp&
2476     get(tuple<_Types...>& __t) noexcept
2477     {
2478       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2479       static_assert(__idx < sizeof...(_Types),
2480           "the type T in std::get<T> must occur exactly once in the tuple");
2481       return std::__get_helper<__idx>(__t);
2482     }
2484   /// Return a reference to the unique element of type _Tp of a tuple rvalue.
2485   template <typename _Tp, typename... _Types>
2486     constexpr _Tp&&
2487     get(tuple<_Types...>&& __t) noexcept
2488     {
2489       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2490       static_assert(__idx < sizeof...(_Types),
2491           "the type T in std::get<T> must occur exactly once in the tuple");
2492       return std::forward<_Tp>(std::__get_helper<__idx>(__t));
2493     }
2495   /// Return a const reference to the unique element of type _Tp of a tuple.
2496   template <typename _Tp, typename... _Types>
2497     constexpr const _Tp&
2498     get(const tuple<_Types...>& __t) noexcept
2499     {
2500       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2501       static_assert(__idx < sizeof...(_Types),
2502           "the type T in std::get<T> must occur exactly once in the tuple");
2503       return std::__get_helper<__idx>(__t);
2504     }
2506   /// Return a const reference to the unique element of type _Tp of
2507   /// a const tuple rvalue.
2508   template <typename _Tp, typename... _Types>
2509     constexpr const _Tp&&
2510     get(const tuple<_Types...>&& __t) noexcept
2511     {
2512       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2513       static_assert(__idx < sizeof...(_Types),
2514           "the type T in std::get<T> must occur exactly once in the tuple");
2515       return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
2516     }
2517 #endif
2519 #if __cpp_lib_three_way_comparison
2520   template<typename... _Tps, typename... _Ups>
2521     requires (sizeof...(_Tps) == sizeof...(_Ups))
2522       && (requires (const _Tps& __t, const _Ups& __u) {
2523         { __t == __u } -> __detail::__boolean_testable;
2524       } && ...)
2525     constexpr bool
2526     operator== [[nodiscard]] (const tuple<_Tps...>& __t,
2527                               const tuple<_Ups...>& __u)
2528     {
2529       return [&]<size_t... _Inds>(index_sequence<_Inds...>) {
2530         // Fold == over the tuples until non-equal elements are found.
2531         return ((std::get<_Inds>(__t) == std::get<_Inds>(__u)) && ...);
2532       }(index_sequence_for<_Tps...>{});
2533     }
2535   template<typename _Cat, typename _Tp, typename _Up, typename _IndexSeq>
2536     [[nodiscard]]
2537     constexpr _Cat
2538     __tuple_cmp(const _Tp& __t, const _Up& __u, _IndexSeq __indices)
2539     {
2540       _Cat __c = _Cat::equivalent;
2542       // Set __c to the comparison result of two corresponding elements.
2543       // Return true they are equivalent.
2544       auto __cmp = [&]<size_t _Ind>(integral_constant<size_t, _Ind>) {
2545         __c = __detail::__synth3way(std::get<_Ind>(__t), std::get<_Ind>(__u));
2546         return __c == 0;
2547       };
2549       [&]<size_t... _Inds>(index_sequence<_Inds...>) {
2550         // Fold __cmp over the tuples until non-equivalent elements are found.
2551         (void)(__cmp(integral_constant<size_t, _Inds>{}) && ...);
2552       }(__indices);
2554       return __c;
2555     }
2557   template<typename... _Tps, typename... _Ups>
2558     requires (sizeof...(_Tps) == sizeof...(_Ups))
2559       && (requires { typename __detail::__synth3way_t<_Tps, _Ups>; } && ...)
2560     constexpr
2561     common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
2562     operator<=> [[nodiscard]] (const tuple<_Tps...>& __t,
2563                                const tuple<_Ups...>& __u)
2564     {
2565       using _Cat
2566         = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
2567       return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
2568     }
2569 #else
2571   // This class performs the comparison operations on tuples
2572   template<typename _Tp, typename _Up, size_t __i, size_t __size>
2573     struct __tuple_compare
2574     {
2575       static constexpr bool
2576       __eq(const _Tp& __t, const _Up& __u)
2577       {
2578         return bool(std::get<__i>(__t) == std::get<__i>(__u))
2579           && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
2580       }
2582       static constexpr bool
2583       __less(const _Tp& __t, const _Up& __u)
2584       {
2585         return bool(std::get<__i>(__t) < std::get<__i>(__u))
2586           || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
2587               && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
2588       }
2589     };
2591   template<typename _Tp, typename _Up, size_t __size>
2592     struct __tuple_compare<_Tp, _Up, __size, __size>
2593     {
2594       static constexpr bool
2595       __eq(const _Tp&, const _Up&) { return true; }
2597       static constexpr bool
2598       __less(const _Tp&, const _Up&) { return false; }
2599     };
2601   template<typename... _TElements, typename... _UElements>
2602     _GLIBCXX_NODISCARD
2603     constexpr bool
2604     operator==(const tuple<_TElements...>& __t,
2605                const tuple<_UElements...>& __u)
2606     {
2607       static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2608           "tuple objects can only be compared if they have equal sizes.");
2609       using __compare = __tuple_compare<tuple<_TElements...>,
2610                                         tuple<_UElements...>,
2611                                         0, sizeof...(_TElements)>;
2612       return __compare::__eq(__t, __u);
2613     }
2615   template<typename... _TElements, typename... _UElements>
2616     _GLIBCXX_NODISCARD
2617     constexpr bool
2618     operator<(const tuple<_TElements...>& __t,
2619               const tuple<_UElements...>& __u)
2620     {
2621       static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2622           "tuple objects can only be compared if they have equal sizes.");
2623       using __compare = __tuple_compare<tuple<_TElements...>,
2624                                         tuple<_UElements...>,
2625                                         0, sizeof...(_TElements)>;
2626       return __compare::__less(__t, __u);
2627     }
2629   template<typename... _TElements, typename... _UElements>
2630     _GLIBCXX_NODISCARD
2631     constexpr bool
2632     operator!=(const tuple<_TElements...>& __t,
2633                const tuple<_UElements...>& __u)
2634     { return !(__t == __u); }
2636   template<typename... _TElements, typename... _UElements>
2637     _GLIBCXX_NODISCARD
2638     constexpr bool
2639     operator>(const tuple<_TElements...>& __t,
2640               const tuple<_UElements...>& __u)
2641     { return __u < __t; }
2643   template<typename... _TElements, typename... _UElements>
2644     _GLIBCXX_NODISCARD
2645     constexpr bool
2646     operator<=(const tuple<_TElements...>& __t,
2647                const tuple<_UElements...>& __u)
2648     { return !(__u < __t); }
2650   template<typename... _TElements, typename... _UElements>
2651     _GLIBCXX_NODISCARD
2652     constexpr bool
2653     operator>=(const tuple<_TElements...>& __t,
2654                const tuple<_UElements...>& __u)
2655     { return !(__t < __u); }
2656 #endif // three_way_comparison
2658   // NB: DR 705.
2659   /// Create a tuple containing copies of the arguments
2660   template<typename... _Elements>
2661     constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
2662     make_tuple(_Elements&&... __args)
2663     {
2664       typedef tuple<typename __decay_and_strip<_Elements>::__type...>
2665         __result_type;
2666       return __result_type(std::forward<_Elements>(__args)...);
2667     }
2669   // _GLIBCXX_RESOLVE_LIB_DEFECTS
2670   // 2275. Why is forward_as_tuple not constexpr?
2671   /// Create a tuple of lvalue or rvalue references to the arguments
2672   template<typename... _Elements>
2673     constexpr tuple<_Elements&&...>
2674     forward_as_tuple(_Elements&&... __args) noexcept
2675     { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2677   /// @cond undocumented
2678   template<size_t, typename, typename, size_t>
2679     struct __make_tuple_impl;
2681   template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
2682     struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
2683     : __make_tuple_impl<_Idx + 1,
2684                         tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
2685                         _Tuple, _Nm>
2686     { };
2688   template<size_t _Nm, typename _Tuple, typename... _Tp>
2689     struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
2690     {
2691       typedef tuple<_Tp...> __type;
2692     };
2694   template<typename _Tuple>
2695     struct __do_make_tuple
2696     : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
2697     { };
2699   // Returns the std::tuple equivalent of a tuple-like type.
2700   template<typename _Tuple>
2701     struct __make_tuple
2702     : public __do_make_tuple<__remove_cvref_t<_Tuple>>
2703     { };
2705   // Combines several std::tuple's into a single one.
2706   template<typename...>
2707     struct __combine_tuples;
2709   template<>
2710     struct __combine_tuples<>
2711     {
2712       typedef tuple<> __type;
2713     };
2715   template<typename... _Ts>
2716     struct __combine_tuples<tuple<_Ts...>>
2717     {
2718       typedef tuple<_Ts...> __type;
2719     };
2721   template<typename... _T1s, typename... _T2s, typename... _Rem>
2722     struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
2723     {
2724       typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
2725                                         _Rem...>::__type __type;
2726     };
2728   // Computes the result type of tuple_cat given a set of tuple-like types.
2729   template<typename... _Tpls>
2730     struct __tuple_cat_result
2731     {
2732       typedef typename __combine_tuples
2733         <typename __make_tuple<_Tpls>::__type...>::__type __type;
2734     };
2736   // Helper to determine the index set for the first tuple-like
2737   // type of a given set.
2738   template<typename...>
2739     struct __make_1st_indices;
2741   template<>
2742     struct __make_1st_indices<>
2743     {
2744       typedef _Index_tuple<> __type;
2745     };
2747   template<typename _Tp, typename... _Tpls>
2748     struct __make_1st_indices<_Tp, _Tpls...>
2749     {
2750       typedef typename _Build_index_tuple<tuple_size<
2751         typename remove_reference<_Tp>::type>::value>::__type __type;
2752     };
2754   // Performs the actual concatenation by step-wise expanding tuple-like
2755   // objects into the elements,  which are finally forwarded into the
2756   // result tuple.
2757   template<typename _Ret, typename _Indices, typename... _Tpls>
2758     struct __tuple_concater;
2760   template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2761     struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2762     {
2763       template<typename... _Us>
2764         static constexpr _Ret
2765         _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2766         {
2767           typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2768           typedef __tuple_concater<_Ret, __idx, _Tpls...>      __next;
2769           return __next::_S_do(std::forward<_Tpls>(__tps)...,
2770                                std::forward<_Us>(__us)...,
2771                                std::get<_Is>(std::forward<_Tp>(__tp))...);
2772         }
2773     };
2775   template<typename _Ret>
2776     struct __tuple_concater<_Ret, _Index_tuple<>>
2777     {
2778       template<typename... _Us>
2779         static constexpr _Ret
2780         _S_do(_Us&&... __us)
2781         {
2782           return _Ret(std::forward<_Us>(__us)...);
2783         }
2784     };
2786   template<typename... _Tps>
2787     struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2788     { };
2789   /// @endcond
2791   /// Create a `tuple` containing all elements from multiple tuple-like objects
2792 #if __cpp_lib_tuple_like // >= C++23
2793   template<__tuple_like... _Tpls>
2794 #else
2795   template<typename... _Tpls, typename = typename
2796            enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2797 #endif
2798     constexpr auto
2799     tuple_cat(_Tpls&&... __tpls)
2800     -> typename __tuple_cat_result<_Tpls...>::__type
2801     {
2802       typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2803       typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2804       typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2805       return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2806     }
2808   // _GLIBCXX_RESOLVE_LIB_DEFECTS
2809   // 2301. Why is tie not constexpr?
2810   /// Return a tuple of lvalue references bound to the arguments
2811   template<typename... _Elements>
2812     constexpr tuple<_Elements&...>
2813     tie(_Elements&... __args) noexcept
2814     { return tuple<_Elements&...>(__args...); }
2816   /// Exchange the values of two tuples
2817   template<typename... _Elements>
2818     _GLIBCXX20_CONSTEXPR
2819     inline
2820 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2821     // Constrained free swap overload, see p0185r1
2822     typename enable_if<__and_<__is_swappable<_Elements>...>::value
2823       >::type
2824 #else
2825     void
2826 #endif
2827     swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
2828     noexcept(noexcept(__x.swap(__y)))
2829     { __x.swap(__y); }
2831 #if __cpp_lib_ranges_zip // >= C++23
2832   template<typename... _Elements>
2833     requires (is_swappable_v<const _Elements> && ...)
2834     constexpr void
2835     swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2836     noexcept(noexcept(__x.swap(__y)))
2837     { __x.swap(__y); }
2838 #endif // C++23
2840 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2841   /// Exchange the values of two const tuples (if const elements can be swapped)
2842   template<typename... _Elements>
2843     _GLIBCXX20_CONSTEXPR
2844     typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2845     swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2846 #endif
2848   /// Partial specialization for tuples
2849   template<typename... _Types, typename _Alloc>
2850     struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2852   // See stl_pair.h...
2853   /** "piecewise construction" using a tuple of arguments for each member.
2854    *
2855    * @param __first Arguments for the first member of the pair.
2856    * @param __second Arguments for the second member of the pair.
2857    *
2858    * The elements of each tuple will be used as the constructor arguments
2859    * for the data members of the pair.
2860   */
2861   template<class _T1, class _T2>
2862     template<typename... _Args1, typename... _Args2>
2863       _GLIBCXX20_CONSTEXPR
2864       inline
2865       pair<_T1, _T2>::
2866       pair(piecewise_construct_t,
2867            tuple<_Args1...> __first, tuple<_Args2...> __second)
2868       : pair(__first, __second,
2869              typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2870              typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2871       { }
2873   template<class _T1, class _T2>
2874     template<typename... _Args1, size_t... _Indexes1,
2875              typename... _Args2, size_t... _Indexes2>
2876       _GLIBCXX20_CONSTEXPR inline
2877       pair<_T1, _T2>::
2878       pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2879            _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2880       : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2881         second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2882       { }
2884 #if defined(__cpp_lib_apply) || defined(__cpp_lib_make_from_tuple) // C++ >= 17
2885   // Unpack a std::tuple into a type trait and use its value.
2886   // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2887   // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2888   // Otherwise the result is false (because we don't know if std::get throws).
2889   template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2890     inline constexpr bool __unpack_std_tuple = false;
2892   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2893     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2894       = _Trait<_Tp, _Up...>::value;
2896   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2897     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2898       = _Trait<_Tp, _Up&...>::value;
2900   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2901     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2902       = _Trait<_Tp, const _Up...>::value;
2904   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2905     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2906       = _Trait<_Tp, const _Up&...>::value;
2907 #endif
2909 #ifdef __cpp_lib_apply // C++ >= 17
2910   template <typename _Fn, typename _Tuple, size_t... _Idx>
2911     constexpr decltype(auto)
2912     __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2913     {
2914       return std::__invoke(std::forward<_Fn>(__f),
2915                            std::get<_Idx>(std::forward<_Tuple>(__t))...);
2916     }
2918 #if __cpp_lib_tuple_like // >= C++23
2919   template <typename _Fn, __tuple_like _Tuple>
2920 #else
2921   template <typename _Fn, typename _Tuple>
2922 #endif
2923     constexpr decltype(auto)
2924     apply(_Fn&& __f, _Tuple&& __t)
2925     noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2926     {
2927       using _Indices
2928         = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2929       return std::__apply_impl(std::forward<_Fn>(__f),
2930                                std::forward<_Tuple>(__t),
2931                                _Indices{});
2932     }
2933 #endif
2935 #ifdef __cpp_lib_make_from_tuple // C++ >= 17
2936   template <typename _Tp, typename _Tuple, size_t... _Idx>
2937     constexpr _Tp
2938     __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
2939     { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
2941 #if __cpp_lib_tuple_like // >= C++23
2942   template <typename _Tp, __tuple_like _Tuple>
2943 #else
2944   template <typename _Tp, typename _Tuple>
2945 #endif
2946     constexpr _Tp
2947     make_from_tuple(_Tuple&& __t)
2948     noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
2949     {
2950       constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
2951 #if __has_builtin(__reference_constructs_from_temporary)
2952       if constexpr (__n == 1)
2953         {
2954           using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
2955           static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
2956         }
2957 #endif
2958       return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
2959                                          make_index_sequence<__n>{});
2960     }
2961 #endif
2963 #if __cpp_lib_tuple_like // >= C++23
2964   template<__tuple_like _TTuple, __tuple_like _UTuple,
2965            template<typename> class _TQual, template<typename> class _UQual,
2966            typename = make_index_sequence<tuple_size_v<_TTuple>>>
2967   struct __tuple_like_common_reference;
2969   template<__tuple_like _TTuple, __tuple_like _UTuple,
2970            template<typename> class _TQual, template<typename> class _UQual,
2971            size_t... _Is>
2972     requires requires
2973       { typename tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2974                                           _UQual<tuple_element_t<_Is, _UTuple>>>...>; }
2975   struct __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual, index_sequence<_Is...>>
2976   {
2977     using type = tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2978                                           _UQual<tuple_element_t<_Is, _UTuple>>>...>;
2979   };
2981   template<__tuple_like _TTuple, __tuple_like _UTuple,
2982            template<typename> class _TQual, template<typename> class _UQual>
2983     requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
2984       && is_same_v<_TTuple, decay_t<_TTuple>>
2985       && is_same_v<_UTuple, decay_t<_UTuple>>
2986       && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
2987       && requires { typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type; }
2988   struct basic_common_reference<_TTuple, _UTuple, _TQual, _UQual>
2989   {
2990     using type = typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type;
2991   };
2993   template<__tuple_like _TTuple, __tuple_like _UTuple,
2994            typename = make_index_sequence<tuple_size_v<_TTuple>>>
2995   struct __tuple_like_common_type;
2997   template<__tuple_like _TTuple, __tuple_like _UTuple, size_t... _Is>
2998     requires requires
2999       { typename tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3000                                    tuple_element_t<_Is, _UTuple>>...>; }
3001   struct __tuple_like_common_type<_TTuple, _UTuple, index_sequence<_Is...>>
3002   {
3003     using type = tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3004                                      tuple_element_t<_Is, _UTuple>>...>;
3005   };
3007   template<__tuple_like _TTuple, __tuple_like _UTuple>
3008     requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
3009       && is_same_v<_TTuple, decay_t<_TTuple>>
3010       && is_same_v<_UTuple, decay_t<_UTuple>>
3011       && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
3012       && requires { typename __tuple_like_common_type<_TTuple, _UTuple>::type; }
3013   struct common_type<_TTuple, _UTuple>
3014   {
3015     using type = typename __tuple_like_common_type<_TTuple, _UTuple>::type;
3016   };
3017 #endif // C++23
3019   /// @}
3021 #undef __glibcxx_no_dangling_refs
3023 _GLIBCXX_END_NAMESPACE_VERSION
3024 } // namespace std
3026 #endif // C++11
3028 #endif // _GLIBCXX_TUPLE