libstdc++/tuple: Guard P2321R2 changes with __cpp_lib_ranges_zip
[official-gcc.git] / libstdc++-v3 / include / std / tuple
blob7a045b3e6a13ca6381e699f4a4f5348d4fe564f8
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 #include <bits/version.h>
55 namespace std _GLIBCXX_VISIBILITY(default)
57 _GLIBCXX_BEGIN_NAMESPACE_VERSION
59   /**
60    *  @addtogroup utilities
61    *  @{
62    */
64   template<typename... _Elements>
65     class tuple;
67   template<typename _Tp>
68     struct __is_empty_non_tuple : is_empty<_Tp> { };
70   // Using EBO for elements that are tuples causes ambiguous base errors.
71   template<typename _El0, typename... _El>
72     struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { };
74   // Use the Empty Base-class Optimization for empty, non-final types.
75   template<typename _Tp>
76     using __empty_not_final
77     = __conditional_t<__is_final(_Tp), false_type,
78                       __is_empty_non_tuple<_Tp>>;
80   template<size_t _Idx, typename _Head,
81            bool = __empty_not_final<_Head>::value>
82     struct _Head_base;
84 #if __has_cpp_attribute(__no_unique_address__)
85   template<size_t _Idx, typename _Head>
86     struct _Head_base<_Idx, _Head, true>
87     {
88       constexpr _Head_base()
89       : _M_head_impl() { }
91       constexpr _Head_base(const _Head& __h)
92       : _M_head_impl(__h) { }
94       constexpr _Head_base(const _Head_base&) = default;
95       constexpr _Head_base(_Head_base&&) = default;
97       template<typename _UHead>
98         constexpr _Head_base(_UHead&& __h)
99         : _M_head_impl(std::forward<_UHead>(__h)) { }
101       _GLIBCXX20_CONSTEXPR
102       _Head_base(allocator_arg_t, __uses_alloc0)
103       : _M_head_impl() { }
105       template<typename _Alloc>
106         _GLIBCXX20_CONSTEXPR
107         _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
108         : _M_head_impl(allocator_arg, *__a._M_a) { }
110       template<typename _Alloc>
111         _GLIBCXX20_CONSTEXPR
112         _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
113         : _M_head_impl(*__a._M_a) { }
115       template<typename _UHead>
116         _GLIBCXX20_CONSTEXPR
117         _Head_base(__uses_alloc0, _UHead&& __uhead)
118         : _M_head_impl(std::forward<_UHead>(__uhead)) { }
120       template<typename _Alloc, typename _UHead>
121         _GLIBCXX20_CONSTEXPR
122         _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
123         : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
124         { }
126       template<typename _Alloc, typename _UHead>
127         _GLIBCXX20_CONSTEXPR
128         _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
129         : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
131       static constexpr _Head&
132       _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
134       static constexpr const _Head&
135       _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
137       [[__no_unique_address__]] _Head _M_head_impl;
138     };
139 #else
140   template<size_t _Idx, typename _Head>
141     struct _Head_base<_Idx, _Head, true>
142     : public _Head
143     {
144       constexpr _Head_base()
145       : _Head() { }
147       constexpr _Head_base(const _Head& __h)
148       : _Head(__h) { }
150       constexpr _Head_base(const _Head_base&) = default;
151       constexpr _Head_base(_Head_base&&) = default;
153       template<typename _UHead>
154         constexpr _Head_base(_UHead&& __h)
155         : _Head(std::forward<_UHead>(__h)) { }
157       _GLIBCXX20_CONSTEXPR
158       _Head_base(allocator_arg_t, __uses_alloc0)
159       : _Head() { }
161       template<typename _Alloc>
162         _GLIBCXX20_CONSTEXPR
163         _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
164         : _Head(allocator_arg, *__a._M_a) { }
166       template<typename _Alloc>
167         _GLIBCXX20_CONSTEXPR
168         _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
169         : _Head(*__a._M_a) { }
171       template<typename _UHead>
172         _GLIBCXX20_CONSTEXPR
173         _Head_base(__uses_alloc0, _UHead&& __uhead)
174         : _Head(std::forward<_UHead>(__uhead)) { }
176       template<typename _Alloc, typename _UHead>
177         _GLIBCXX20_CONSTEXPR
178         _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
179         : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
181       template<typename _Alloc, typename _UHead>
182         _GLIBCXX20_CONSTEXPR
183         _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
184         : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
186       static constexpr _Head&
187       _M_head(_Head_base& __b) noexcept { return __b; }
189       static constexpr const _Head&
190       _M_head(const _Head_base& __b) noexcept { return __b; }
191     };
192 #endif
194   template<size_t _Idx, typename _Head>
195     struct _Head_base<_Idx, _Head, false>
196     {
197       constexpr _Head_base()
198       : _M_head_impl() { }
200       constexpr _Head_base(const _Head& __h)
201       : _M_head_impl(__h) { }
203       constexpr _Head_base(const _Head_base&) = default;
204       constexpr _Head_base(_Head_base&&) = default;
206       template<typename _UHead>
207         constexpr _Head_base(_UHead&& __h)
208         : _M_head_impl(std::forward<_UHead>(__h)) { }
210       _GLIBCXX20_CONSTEXPR
211       _Head_base(allocator_arg_t, __uses_alloc0)
212       : _M_head_impl() { }
214       template<typename _Alloc>
215         _GLIBCXX20_CONSTEXPR
216         _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
217         : _M_head_impl(allocator_arg, *__a._M_a) { }
219       template<typename _Alloc>
220         _GLIBCXX20_CONSTEXPR
221         _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
222         : _M_head_impl(*__a._M_a) { }
224       template<typename _UHead>
225         _GLIBCXX20_CONSTEXPR
226         _Head_base(__uses_alloc0, _UHead&& __uhead)
227         : _M_head_impl(std::forward<_UHead>(__uhead)) { }
229       template<typename _Alloc, typename _UHead>
230         _GLIBCXX20_CONSTEXPR
231         _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
232         : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
233         { }
235       template<typename _Alloc, typename _UHead>
236         _GLIBCXX20_CONSTEXPR
237         _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
238         : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
240       static constexpr _Head&
241       _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
243       static constexpr const _Head&
244       _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
246       _Head _M_head_impl;
247     };
249   /**
250    * Contains the actual implementation of the @c tuple template, stored
251    * as a recursive inheritance hierarchy from the first element (most
252    * derived class) to the last (least derived class). The @c Idx
253    * parameter gives the 0-based index of the element stored at this
254    * point in the hierarchy; we use it to implement a constant-time
255    * get() operation.
256    */
257   template<size_t _Idx, typename... _Elements>
258     struct _Tuple_impl;
260   /**
261    * Recursive tuple implementation. Here we store the @c Head element
262    * and derive from a @c Tuple_impl containing the remaining elements
263    * (which contains the @c Tail).
264    */
265   template<size_t _Idx, typename _Head, typename... _Tail>
266     struct _Tuple_impl<_Idx, _Head, _Tail...>
267     : public _Tuple_impl<_Idx + 1, _Tail...>,
268       private _Head_base<_Idx, _Head>
269     {
270       template<size_t, typename...> friend struct _Tuple_impl;
272       typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
273       typedef _Head_base<_Idx, _Head> _Base;
275       static constexpr _Head&
276       _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
278       static constexpr const _Head&
279       _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
281       static constexpr _Inherited&
282       _M_tail(_Tuple_impl& __t) noexcept { return __t; }
284       static constexpr const _Inherited&
285       _M_tail(const _Tuple_impl& __t) noexcept { return __t; }
287       constexpr _Tuple_impl()
288       : _Inherited(), _Base() { }
290       explicit constexpr
291       _Tuple_impl(const _Head& __head, const _Tail&... __tail)
292       : _Inherited(__tail...), _Base(__head)
293       { }
295       template<typename _UHead, typename... _UTail,
296                typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
297         explicit constexpr
298         _Tuple_impl(_UHead&& __head, _UTail&&... __tail)
299         : _Inherited(std::forward<_UTail>(__tail)...),
300           _Base(std::forward<_UHead>(__head))
301         { }
303       constexpr _Tuple_impl(const _Tuple_impl&) = default;
305       // _GLIBCXX_RESOLVE_LIB_DEFECTS
306       // 2729. Missing SFINAE on std::pair::operator=
307       _Tuple_impl& operator=(const _Tuple_impl&) = delete;
309       _Tuple_impl(_Tuple_impl&&) = default;
311       template<typename... _UElements>
312         constexpr
313         _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
314         : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
315           _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
316         { }
318       template<typename _UHead, typename... _UTails>
319         constexpr
320         _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
321         : _Inherited(std::move
322                      (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
323           _Base(std::forward<_UHead>
324                 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
325         { }
327 #if __cpp_lib_ranges_zip // >= C++23
328       template<typename... _UElements>
329         constexpr
330         _Tuple_impl(_Tuple_impl<_Idx, _UElements...>& __in)
331         : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
332           _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
333         { }
335       template<typename _UHead, typename... _UTails>
336         constexpr
337         _Tuple_impl(const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
338         : _Inherited(std::move
339                      (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
340           _Base(std::forward<const _UHead>
341                 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
342         { }
343 #endif // C++23
345       template<typename _Alloc>
346         _GLIBCXX20_CONSTEXPR
347         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
348         : _Inherited(__tag, __a),
349           _Base(__tag, __use_alloc<_Head>(__a))
350         { }
352       template<typename _Alloc>
353         _GLIBCXX20_CONSTEXPR
354         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
355                     const _Head& __head, const _Tail&... __tail)
356         : _Inherited(__tag, __a, __tail...),
357           _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head)
358         { }
360       template<typename _Alloc, typename _UHead, typename... _UTail,
361                typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
362         _GLIBCXX20_CONSTEXPR
363         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
364                     _UHead&& __head, _UTail&&... __tail)
365         : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
366           _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
367                 std::forward<_UHead>(__head))
368         { }
370       template<typename _Alloc>
371         _GLIBCXX20_CONSTEXPR
372         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
373                     const _Tuple_impl& __in)
374         : _Inherited(__tag, __a, _M_tail(__in)),
375           _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in))
376         { }
378       template<typename _Alloc>
379         _GLIBCXX20_CONSTEXPR
380         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
381                     _Tuple_impl&& __in)
382         : _Inherited(__tag, __a, std::move(_M_tail(__in))),
383           _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
384                 std::forward<_Head>(_M_head(__in)))
385         { }
387       template<typename _Alloc, typename _UHead, typename... _UTails>
388         _GLIBCXX20_CONSTEXPR
389         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
390                     const _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
391         : _Inherited(__tag, __a,
392                      _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
393           _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
394                 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
395         { }
397       template<typename _Alloc, typename _UHead, typename... _UTails>
398         _GLIBCXX20_CONSTEXPR
399         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
400                     _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
401         : _Inherited(__tag, __a, std::move
402                      (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
403           _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
404                 std::forward<_UHead>
405                 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
406         { }
408 #if __cpp_lib_ranges_zip // >= C++23
409       template<typename _Alloc, typename _UHead, typename... _UTails>
410         constexpr
411         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
412                     _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
413         : _Inherited(__tag, __a,
414                      _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
415           _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
416                 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
417         { }
419       template<typename _Alloc, typename _UHead, typename... _UTails>
420         constexpr
421         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
422                     const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
423         : _Inherited(__tag, __a, std::move
424                      (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
425           _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
426                 std::forward<const _UHead>
427                 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
428         { }
429 #endif // C++23
431       template<typename... _UElements>
432         _GLIBCXX20_CONSTEXPR
433         void
434         _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in)
435         {
436           _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
437           _M_tail(*this)._M_assign(
438               _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
439         }
441       template<typename _UHead, typename... _UTails>
442         _GLIBCXX20_CONSTEXPR
443         void
444         _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
445         {
446           _M_head(*this) = std::forward<_UHead>
447             (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
448           _M_tail(*this)._M_assign(
449               std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
450         }
452 #if __cpp_lib_ranges_zip // >= C++23
453       template<typename... _UElements>
454         constexpr void
455         _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) const
456         {
457           _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
458           _M_tail(*this)._M_assign(
459               _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
460         }
462       template<typename _UHead, typename... _UTails>
463         constexpr void
464         _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) const
465         {
466           _M_head(*this) = std::forward<_UHead>
467             (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
468           _M_tail(*this)._M_assign(
469               std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
470         }
471 #endif // C++23
473     protected:
474       _GLIBCXX20_CONSTEXPR
475       void
476       _M_swap(_Tuple_impl& __in)
477       {
478         using std::swap;
479         swap(_M_head(*this), _M_head(__in));
480         _Inherited::_M_swap(_M_tail(__in));
481       }
483 #if __cpp_lib_ranges_zip // >= C++23
484       constexpr void
485       _M_swap(const _Tuple_impl& __in) const
486       {
487         using std::swap;
488         swap(_M_head(*this), _M_head(__in));
489         _Inherited::_M_swap(_M_tail(__in));
490       }
491 #endif // C++23
492     };
494   // Basis case of inheritance recursion.
495   template<size_t _Idx, typename _Head>
496     struct _Tuple_impl<_Idx, _Head>
497     : private _Head_base<_Idx, _Head>
498     {
499       template<size_t, typename...> friend struct _Tuple_impl;
501       typedef _Head_base<_Idx, _Head> _Base;
503       static constexpr _Head&
504       _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
506       static constexpr const _Head&
507       _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
509       constexpr
510       _Tuple_impl()
511       : _Base() { }
513       explicit constexpr
514       _Tuple_impl(const _Head& __head)
515       : _Base(__head)
516       { }
518       template<typename _UHead>
519         explicit constexpr
520         _Tuple_impl(_UHead&& __head)
521         : _Base(std::forward<_UHead>(__head))
522         { }
524       constexpr _Tuple_impl(const _Tuple_impl&) = default;
526       // _GLIBCXX_RESOLVE_LIB_DEFECTS
527       // 2729. Missing SFINAE on std::pair::operator=
528       _Tuple_impl& operator=(const _Tuple_impl&) = delete;
530 #if _GLIBCXX_INLINE_VERSION
531       _Tuple_impl(_Tuple_impl&&) = default;
532 #else
533       constexpr
534       _Tuple_impl(_Tuple_impl&& __in)
535       noexcept(is_nothrow_move_constructible<_Head>::value)
536       : _Base(static_cast<_Base&&>(__in))
537       { }
538 #endif
540       template<typename _UHead>
541         constexpr
542         _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in)
543         : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
544         { }
546       template<typename _UHead>
547         constexpr
548         _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in)
549         : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
550         { }
552 #if __cpp_lib_ranges_zip // >= C++23
553       template<typename _UHead>
554         constexpr
555         _Tuple_impl(_Tuple_impl<_Idx, _UHead>& __in)
556         : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
557         { }
559       template<typename _UHead>
560         constexpr
561         _Tuple_impl(const _Tuple_impl<_Idx, _UHead>&& __in)
562         : _Base(std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
563         { }
564 #endif // C++23
566       template<typename _Alloc>
567         _GLIBCXX20_CONSTEXPR
568         _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
569         : _Base(__tag, __use_alloc<_Head>(__a))
570         { }
572       template<typename _Alloc>
573         _GLIBCXX20_CONSTEXPR
574         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
575                     const _Head& __head)
576         : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), __head)
577         { }
579       template<typename _Alloc, typename _UHead>
580         _GLIBCXX20_CONSTEXPR
581         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
582                     _UHead&& __head)
583         : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
584                 std::forward<_UHead>(__head))
585         { }
587       template<typename _Alloc>
588         _GLIBCXX20_CONSTEXPR
589         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
590                     const _Tuple_impl& __in)
591         : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), _M_head(__in))
592         { }
594       template<typename _Alloc>
595         _GLIBCXX20_CONSTEXPR
596         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
597                     _Tuple_impl&& __in)
598         : _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
599                 std::forward<_Head>(_M_head(__in)))
600         { }
602       template<typename _Alloc, typename _UHead>
603         _GLIBCXX20_CONSTEXPR
604         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
605                     const _Tuple_impl<_Idx, _UHead>& __in)
606         : _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
607                 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
608         { }
610       template<typename _Alloc, typename _UHead>
611         _GLIBCXX20_CONSTEXPR
612         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
613                     _Tuple_impl<_Idx, _UHead>&& __in)
614         : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
615                 std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
616         { }
618 #if __cpp_lib_ranges_zip // >= C++23
619       template<typename _Alloc, typename _UHead>
620         constexpr
621         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
622                     _Tuple_impl<_Idx, _UHead>& __in)
623         : _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
624                 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
625         { }
627       template<typename _Alloc, typename _UHead>
628         constexpr
629         _Tuple_impl(allocator_arg_t, const _Alloc& __a,
630                     const _Tuple_impl<_Idx, _UHead>&& __in)
631         : _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
632                 std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
633         { }
634 #endif // C++23
636       template<typename _UHead>
637         _GLIBCXX20_CONSTEXPR
638         void
639         _M_assign(const _Tuple_impl<_Idx, _UHead>& __in)
640         {
641           _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
642         }
644       template<typename _UHead>
645         _GLIBCXX20_CONSTEXPR
646         void
647         _M_assign(_Tuple_impl<_Idx, _UHead>&& __in)
648         {
649           _M_head(*this)
650             = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
651         }
653 #if __cpp_lib_ranges_zip // >= C++23
654       template<typename _UHead>
655         constexpr void
656         _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) const
657         {
658           _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
659         }
661       template<typename _UHead>
662         constexpr void
663         _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) const
664         {
665           _M_head(*this)
666             = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
667         }
668 #endif // C++23
670     protected:
671       _GLIBCXX20_CONSTEXPR
672       void
673       _M_swap(_Tuple_impl& __in)
674       {
675         using std::swap;
676         swap(_M_head(*this), _M_head(__in));
677       }
679 #if __cpp_lib_ranges_zip // >= C++23
680       constexpr void
681       _M_swap(const _Tuple_impl& __in) const
682       {
683         using std::swap;
684         swap(_M_head(*this), _M_head(__in));
685       }
686 #endif // C++23
687     };
689   // Concept utility functions, reused in conditionally-explicit
690   // constructors.
691   template<bool, typename... _Types>
692     struct _TupleConstraints
693     {
694       template<typename... _UTypes>
695         using __constructible = __and_<is_constructible<_Types, _UTypes>...>;
697       template<typename... _UTypes>
698         using __convertible = __and_<is_convertible<_UTypes, _Types>...>;
700       // Constraint for a non-explicit constructor.
701       // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
702       // and every Ui is implicitly convertible to Ti.
703       template<typename... _UTypes>
704         static constexpr bool __is_implicitly_constructible()
705         {
706           return __and_<__constructible<_UTypes...>,
707                         __convertible<_UTypes...>
708                         >::value;
709         }
711       // Constraint for a non-explicit constructor.
712       // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
713       // but not every Ui is implicitly convertible to Ti.
714       template<typename... _UTypes>
715         static constexpr bool __is_explicitly_constructible()
716         {
717           return __and_<__constructible<_UTypes...>,
718                         __not_<__convertible<_UTypes...>>
719                         >::value;
720         }
722       static constexpr bool __is_implicitly_default_constructible()
723       {
724         return __and_<std::__is_implicitly_default_constructible<_Types>...
725                       >::value;
726       }
728       static constexpr bool __is_explicitly_default_constructible()
729       {
730         return __and_<is_default_constructible<_Types>...,
731                       __not_<__and_<
732                         std::__is_implicitly_default_constructible<_Types>...>
733                       >>::value;
734       }
735     };
737   // Partial specialization used when a required precondition isn't met,
738   // e.g. when sizeof...(_Types) != sizeof...(_UTypes).
739   template<typename... _Types>
740     struct _TupleConstraints<false, _Types...>
741     {
742       template<typename... _UTypes>
743         static constexpr bool __is_implicitly_constructible()
744         { return false; }
746       template<typename... _UTypes>
747         static constexpr bool __is_explicitly_constructible()
748         { return false; }
749     };
751   /// Primary class template, tuple
752   template<typename... _Elements>
753     class tuple : public _Tuple_impl<0, _Elements...>
754     {
755       using _Inherited = _Tuple_impl<0, _Elements...>;
757 #if __cpp_concepts && __cpp_consteval && __cpp_conditional_explicit // >= C++20
758       template<typename... _UTypes>
759         static consteval bool
760         __constructible()
761         {
762           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
763             return __and_v<is_constructible<_Elements, _UTypes>...>;
764           else
765             return false;
766         }
768       template<typename... _UTypes>
769         static consteval bool
770         __nothrow_constructible()
771         {
772           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
773             return __and_v<is_nothrow_constructible<_Elements, _UTypes>...>;
774           else
775             return false;
776         }
778       template<typename... _UTypes>
779         static consteval bool
780         __convertible()
781         {
782           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
783             return __and_v<is_convertible<_UTypes, _Elements>...>;
784           else
785             return false;
786         }
788       // _GLIBCXX_RESOLVE_LIB_DEFECTS
789       // 3121. tuple constructor constraints for UTypes&&... overloads
790       template<typename... _UTypes>
791         static consteval bool
792         __disambiguating_constraint()
793         {
794           if constexpr (sizeof...(_Elements) != sizeof...(_UTypes))
795             return false;
796           else if constexpr (sizeof...(_Elements) == 1)
797             {
798               using _U0 = typename _Nth_type<0, _UTypes...>::type;
799               return !is_same_v<remove_cvref_t<_U0>, tuple>;
800             }
801           else if constexpr (sizeof...(_Elements) < 4)
802             {
803               using _U0 = typename _Nth_type<0, _UTypes...>::type;
804               if constexpr (!is_same_v<remove_cvref_t<_U0>, allocator_arg_t>)
805                 return true;
806               else
807                 {
808                   using _T0 = typename _Nth_type<0, _Elements...>::type;
809                   return is_same_v<remove_cvref_t<_T0>, allocator_arg_t>;
810                 }
811             }
812           return true;
813         }
815       // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
816       // and the single element in Types can be initialized from TUPLE,
817       // or is the same type as tuple_element_t<0, TUPLE>.
818       template<typename _Tuple>
819         static consteval bool
820         __use_other_ctor()
821         {
822           if constexpr (sizeof...(_Elements) != 1)
823             return false;
824           else if constexpr (is_same_v<remove_cvref_t<_Tuple>, tuple>)
825             return true; // Should use a copy/move constructor instead.
826           else
827             {
828               using _Tp = typename _Nth_type<0, _Elements...>::type;
829               if constexpr (is_convertible_v<_Tuple, _Tp>)
830                 return true;
831               else if constexpr (is_constructible_v<_Tp, _Tuple>)
832                 return true;
833             }
834           return false;
835         }
837       template<typename... _Up>
838         static consteval bool
839         __dangles()
840         {
841 #if __has_builtin(__reference_constructs_from_temporary)
842           return (__reference_constructs_from_temporary(_Elements, _Up&&)
843                     || ...);
844 #else
845           return false;
846 #endif
847         }
849     public:
850       constexpr
851       explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
852       tuple()
853       noexcept((is_nothrow_default_constructible_v<_Elements> && ...))
854       requires (is_default_constructible_v<_Elements> && ...)
855       : _Inherited()
856       { }
858       constexpr explicit(!__convertible<const _Elements&...>())
859       tuple(const _Elements&... __elements)
860       noexcept(__nothrow_constructible<const _Elements&...>())
861       requires (__constructible<const _Elements&...>())
862       : _Inherited(__elements...)
863       { }
865       template<typename... _UTypes>
866         requires (__disambiguating_constraint<_UTypes...>())
867           && (__constructible<_UTypes...>())
868           && (!__dangles<_UTypes...>())
869         constexpr explicit(!__convertible<_UTypes...>())
870         tuple(_UTypes&&... __u)
871         noexcept(__nothrow_constructible<_UTypes...>())
872         : _Inherited(std::forward<_UTypes>(__u)...)
873         { }
875       template<typename... _UTypes>
876         requires (__disambiguating_constraint<_UTypes...>())
877           && (__constructible<_UTypes...>())
878           && (__dangles<_UTypes...>())
879         tuple(_UTypes&&...) = delete;
881       constexpr tuple(const tuple&) = default;
883       constexpr tuple(tuple&&) = default;
885       template<typename... _UTypes>
886         requires (__constructible<const _UTypes&...>())
887           && (!__use_other_ctor<const tuple<_UTypes...>&>())
888           && (!__dangles<const _UTypes&...>())
889         constexpr explicit(!__convertible<const _UTypes&...>())
890         tuple(const tuple<_UTypes...>& __u)
891         noexcept(__nothrow_constructible<const _UTypes&...>())
892         : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
893         { }
895       template<typename... _UTypes>
896         requires (__constructible<const _UTypes&...>())
897           && (!__use_other_ctor<const tuple<_UTypes...>&>())
898           && (__dangles<const _UTypes&...>())
899         tuple(const tuple<_UTypes...>&) = delete;
901       template<typename... _UTypes>
902         requires (__constructible<_UTypes...>())
903           && (!__use_other_ctor<tuple<_UTypes...>>())
904           && (!__dangles<_UTypes...>())
905         constexpr explicit(!__convertible<_UTypes...>())
906         tuple(tuple<_UTypes...>&& __u)
907         noexcept(__nothrow_constructible<_UTypes...>())
908         : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
909         { }
911       template<typename... _UTypes>
912         requires (__constructible<_UTypes...>())
913           && (!__use_other_ctor<tuple<_UTypes...>>())
914           && (__dangles<_UTypes...>())
915         tuple(tuple<_UTypes...>&&) = delete;
917 #if __cpp_lib_ranges_zip // >= C++23
918       template<typename... _UTypes>
919         requires (__constructible<_UTypes&...>())
920           && (!__use_other_ctor<tuple<_UTypes...>&>())
921           && (!__dangles<_UTypes&...>())
922         constexpr explicit(!__convertible<_UTypes&...>())
923         tuple(tuple<_UTypes...>& __u)
924         noexcept(__nothrow_constructible<_UTypes&...>())
925         : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
926         { }
928       template<typename... _UTypes>
929         requires (__constructible<_UTypes&...>())
930           && (!__use_other_ctor<tuple<_UTypes...>&>())
931           && (__dangles<_UTypes&...>())
932         tuple(tuple<_UTypes...>&) = delete;
934       template<typename... _UTypes>
935         requires (__constructible<const _UTypes...>())
936           && (!__use_other_ctor<const tuple<_UTypes...>>())
937           && (!__dangles<const _UTypes...>())
938         constexpr explicit(!__convertible<const _UTypes...>())
939         tuple(const tuple<_UTypes...>&& __u)
940         noexcept(__nothrow_constructible<const _UTypes...>())
941         : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
942         { }
944       template<typename... _UTypes>
945         requires (__constructible<const _UTypes...>())
946           && (!__use_other_ctor<const tuple<_UTypes...>>())
947           && (__dangles<const _UTypes...>())
948         tuple(const tuple<_UTypes...>&&) = delete;
949 #endif // C++23
951       template<typename _U1, typename _U2>
952         requires (sizeof...(_Elements) == 2)
953           && (__constructible<const _U1&, const _U2&>())
954           && (!__dangles<const _U1&, const _U2&>())
955         constexpr explicit(!__convertible<const _U1&, const _U2&>())
956         tuple(const pair<_U1, _U2>& __u)
957         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
958         : _Inherited(__u.first, __u.second)
959         { }
961       template<typename _U1, typename _U2>
962         requires (sizeof...(_Elements) == 2)
963           && (__constructible<const _U1&, const _U2&>())
964           && (__dangles<const _U1&, const _U2&>())
965         tuple(const pair<_U1, _U2>&) = delete;
967       template<typename _U1, typename _U2>
968         requires (sizeof...(_Elements) == 2)
969           && (__constructible<_U1, _U2>())
970           && (!__dangles<_U1, _U2>())
971         constexpr explicit(!__convertible<_U1, _U2>())
972         tuple(pair<_U1, _U2>&& __u)
973         noexcept(__nothrow_constructible<_U1, _U2>())
974         : _Inherited(std::forward<_U1>(__u.first),
975                      std::forward<_U2>(__u.second))
976         { }
978       template<typename _U1, typename _U2>
979         requires (sizeof...(_Elements) == 2)
980           && (__constructible<_U1, _U2>())
981           && (__dangles<_U1, _U2>())
982         tuple(pair<_U1, _U2>&&) = delete;
984 #if __cpp_lib_ranges_zip // >= C++23
985       template<typename _U1, typename _U2>
986         requires (sizeof...(_Elements) == 2)
987           && (__constructible<_U1&, _U2&>())
988           && (!__dangles<_U1&, _U2&>())
989         constexpr explicit(!__convertible<_U1&, _U2&>())
990         tuple(pair<_U1, _U2>& __u)
991         noexcept(__nothrow_constructible<_U1&, _U2&>())
992         : _Inherited(__u.first, __u.second)
993         { }
995       template<typename _U1, typename _U2>
996         requires (sizeof...(_Elements) == 2)
997           && (__constructible<_U1&, _U2&>())
998           && (__dangles<_U1&, _U2&>())
999         tuple(pair<_U1, _U2>&) = delete;
1001       template<typename _U1, typename _U2>
1002         requires (sizeof...(_Elements) == 2)
1003           && (__constructible<const _U1, const _U2>())
1004           && (!__dangles<const _U1, const _U2>())
1005         constexpr explicit(!__convertible<const _U1, const _U2>())
1006         tuple(const pair<_U1, _U2>&& __u)
1007         noexcept(__nothrow_constructible<const _U1, const _U2>())
1008         : _Inherited(std::forward<const _U1>(__u.first),
1009                      std::forward<const _U2>(__u.second))
1010         { }
1012       template<typename _U1, typename _U2>
1013         requires (sizeof...(_Elements) == 2)
1014           && (__constructible<const _U1, const _U2>())
1015           && (__dangles<const _U1, const _U2>())
1016         tuple(const pair<_U1, _U2>&&) = delete;
1017 #endif // C++23
1019 #if 0 && __cpp_lib_tuple_like // >= C++23
1020       template<__tuple_like _UTuple>
1021         constexpr explicit(...)
1022         tuple(_UTuple&& __u);
1023 #endif // C++23
1025       // Allocator-extended constructors.
1027       template<typename _Alloc>
1028         constexpr
1029         explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
1030         tuple(allocator_arg_t __tag, const _Alloc& __a)
1031         requires (is_default_constructible_v<_Elements> && ...)
1032         : _Inherited(__tag, __a)
1033         { }
1035       template<typename _Alloc>
1036         constexpr explicit(!__convertible<const _Elements&...>())
1037         tuple(allocator_arg_t __tag, const _Alloc& __a,
1038               const _Elements&... __elements)
1039         requires (__constructible<const _Elements&...>())
1040         : _Inherited(__tag, __a, __elements...)
1041         { }
1043       template<typename _Alloc, typename... _UTypes>
1044         requires (__disambiguating_constraint<_UTypes...>())
1045           && (__constructible<_UTypes...>())
1046           && (!__dangles<_UTypes...>())
1047         constexpr explicit(!__convertible<_UTypes...>())
1048         tuple(allocator_arg_t __tag, const _Alloc& __a, _UTypes&&... __u)
1049         : _Inherited(__tag, __a, std::forward<_UTypes>(__u)...)
1050         { }
1052       template<typename _Alloc, typename... _UTypes>
1053         requires (__disambiguating_constraint<_UTypes...>())
1054           && (__constructible<_UTypes...>())
1055           && (__dangles<_UTypes...>())
1056         tuple(allocator_arg_t, const _Alloc&, _UTypes&&...) = delete;
1058       template<typename _Alloc>
1059         constexpr
1060         tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __u)
1061         : _Inherited(__tag, __a, static_cast<const _Inherited&>(__u))
1062         { }
1064       template<typename _Alloc>
1065         requires (__constructible<_Elements...>())
1066         constexpr
1067         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __u)
1068         : _Inherited(__tag, __a, static_cast<_Inherited&&>(__u))
1069         { }
1071       template<typename _Alloc, typename... _UTypes>
1072         requires (__constructible<const _UTypes&...>())
1073           && (!__use_other_ctor<const tuple<_UTypes...>&>())
1074           && (!__dangles<const _UTypes&...>())
1075         constexpr explicit(!__convertible<const _UTypes&...>())
1076         tuple(allocator_arg_t __tag, const _Alloc& __a,
1077               const tuple<_UTypes...>& __u)
1078         : _Inherited(__tag, __a,
1079                      static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1080         { }
1082       template<typename _Alloc, typename... _UTypes>
1083         requires (__constructible<const _UTypes&...>())
1084           && (!__use_other_ctor<const tuple<_UTypes...>&>())
1085           && (__dangles<const _UTypes&...>())
1086         tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&) = delete;
1088       template<typename _Alloc, typename... _UTypes>
1089         requires (__constructible<_UTypes...>())
1090           && (!__use_other_ctor<tuple<_UTypes...>>())
1091           && (!__dangles<_UTypes...>())
1092         constexpr explicit(!__use_other_ctor<tuple<_UTypes...>>())
1093         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>&& __u)
1094         : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1095         { }
1097       template<typename _Alloc, typename... _UTypes>
1098         requires (__constructible<_UTypes...>())
1099           && (!__use_other_ctor<tuple<_UTypes...>>())
1100           && (__dangles<_UTypes...>())
1101         tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&&) = delete;
1103 #if __cpp_lib_ranges_zip // >= C++23
1104       template<typename _Alloc, typename... _UTypes>
1105         requires (__constructible<_UTypes&...>())
1106           && (!__use_other_ctor<tuple<_UTypes...>&>())
1107           && (!__dangles<_UTypes&...>())
1108         constexpr explicit(!__convertible<_UTypes&...>())
1109         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>& __u)
1110         : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1111         { }
1113       template<typename _Alloc, typename... _UTypes>
1114         requires (__constructible<_UTypes&...>())
1115           && (!__use_other_ctor<tuple<_UTypes...>&>())
1116           && (__dangles<_UTypes&...>())
1117         tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&) = delete;
1119       template<typename _Alloc, typename... _UTypes>
1120         requires (__constructible<const _UTypes...>())
1121           && (!__use_other_ctor<const tuple<_UTypes...>>())
1122           && (!__dangles<const _UTypes...>())
1123         constexpr explicit(!__convertible<const _UTypes...>())
1124         tuple(allocator_arg_t __tag, const _Alloc& __a,
1125               const tuple<_UTypes...>&& __u)
1126         : _Inherited(__tag, __a,
1127                      static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1128         { }
1130       template<typename _Alloc, typename... _UTypes>
1131         requires (__constructible<const _UTypes...>())
1132           && (!__use_other_ctor<const tuple<_UTypes...>>())
1133           && (__dangles<const _UTypes...>())
1134         tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&&) = delete;
1135 #endif // C++23
1137       template<typename _Alloc, typename _U1, typename _U2>
1138         requires (sizeof...(_Elements) == 2)
1139           && (__constructible<const _U1&, const _U2&>())
1140           && (!__dangles<const _U1&, const _U2&>())
1141         constexpr explicit(!__convertible<const _U1&, const _U2&>())
1142         tuple(allocator_arg_t __tag, const _Alloc& __a,
1143               const pair<_U1, _U2>& __u)
1144         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1145         : _Inherited(__tag, __a, __u.first, __u.second)
1146         { }
1148       template<typename _Alloc, typename _U1, typename _U2>
1149         requires (sizeof...(_Elements) == 2)
1150           && (__constructible<const _U1&, const _U2&>())
1151           && (__dangles<const _U1&, const _U2&>())
1152         tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&) = delete;
1154       template<typename _Alloc, typename _U1, typename _U2>
1155         requires (sizeof...(_Elements) == 2)
1156           && (__constructible<_U1, _U2>())
1157           && (!__dangles<_U1, _U2>())
1158         constexpr explicit(!__convertible<_U1, _U2>())
1159         tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __u)
1160         noexcept(__nothrow_constructible<_U1, _U2>())
1161         : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1162         { }
1164       template<typename _Alloc, typename _U1, typename _U2>
1165         requires (sizeof...(_Elements) == 2)
1166           && (__constructible<_U1, _U2>())
1167           && (__dangles<_U1, _U2>())
1168         tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&) = delete;
1170 #if __cpp_lib_ranges_zip // >= C++23
1171       template<typename _Alloc, typename _U1, typename _U2>
1172         requires (sizeof...(_Elements) == 2)
1173           && (__constructible<_U1&, _U2&>())
1174           && (!__dangles<_U1&, _U2&>())
1175         constexpr explicit(!__convertible<_U1&, _U2&>())
1176         tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>& __u)
1177         noexcept(__nothrow_constructible<_U1&, _U2&>())
1178         : _Inherited(__tag, __a, __u.first, __u.second)
1179         { }
1181       template<typename _Alloc, typename _U1, typename _U2>
1182         requires (sizeof...(_Elements) == 2)
1183           && (__constructible<_U1&, _U2&>())
1184           && (__dangles<_U1&, _U2&>())
1185         tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&) = delete;
1187       template<typename _Alloc, typename _U1, typename _U2>
1188         requires (sizeof...(_Elements) == 2)
1189           && (__constructible<const _U1, const _U2>())
1190           && (!__dangles<const _U1, const _U2>())
1191         constexpr explicit(!__convertible<const _U1, const _U2>())
1192         tuple(allocator_arg_t __tag, const _Alloc& __a,
1193         const pair<_U1, _U2>&& __u)
1194         noexcept(__nothrow_constructible<const _U1, const _U2>())
1195         : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1196         { }
1198       template<typename _Alloc, typename _U1, typename _U2>
1199         requires (sizeof...(_Elements) == 2)
1200           && (__constructible<const _U1, const _U2>())
1201           && (__dangles<const _U1, const _U2>())
1202         tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&&) = delete;
1203 #endif // C++23
1205 #if 0 && __cpp_lib_tuple_like // >= C++23
1206       template<typename _Alloc, __tuple_like _UTuple>
1207         constexpr explicit(...)
1208         tuple(allocator_arg_t __tag, const _Alloc& __a, _UTuple&& __u);
1209 #endif // C++23
1211 #else // !(concepts && conditional_explicit)
1213       template<bool _Cond>
1214         using _TCC = _TupleConstraints<_Cond, _Elements...>;
1216       // Constraint for non-explicit default constructor
1217       template<bool _Dummy>
1218         using _ImplicitDefaultCtor = __enable_if_t<
1219           _TCC<_Dummy>::__is_implicitly_default_constructible(),
1220           bool>;
1222       // Constraint for explicit default constructor
1223       template<bool _Dummy>
1224         using _ExplicitDefaultCtor = __enable_if_t<
1225           _TCC<_Dummy>::__is_explicitly_default_constructible(),
1226           bool>;
1228       // Constraint for non-explicit constructors
1229       template<bool _Cond, typename... _Args>
1230         using _ImplicitCtor = __enable_if_t<
1231           _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
1232           bool>;
1234       // Constraint for non-explicit constructors
1235       template<bool _Cond, typename... _Args>
1236         using _ExplicitCtor = __enable_if_t<
1237           _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
1238           bool>;
1240       // Condition for noexcept-specifier of a constructor.
1241       template<typename... _UElements>
1242         static constexpr bool __nothrow_constructible()
1243         {
1244           return
1245             __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
1246         }
1248       // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1.
1249       template<typename _Up>
1250         static constexpr bool __valid_args()
1251         {
1252           return sizeof...(_Elements) == 1
1253             && !is_same<tuple, __remove_cvref_t<_Up>>::value;
1254         }
1256       // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1.
1257       template<typename, typename, typename... _Tail>
1258         static constexpr bool __valid_args()
1259         { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); }
1261       /* Constraint for constructors with a tuple<UTypes...> parameter ensures
1262        * that the constructor is only viable when it would not interfere with
1263        * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&).
1264        * Such constructors are only viable if:
1265        * either sizeof...(Types) != 1,
1266        * or (when Types... expands to T and UTypes... expands to U)
1267        * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>,
1268        * and is_same_v<T, U> are all false.
1269        */
1270       template<typename _Tuple, typename = tuple,
1271                typename = __remove_cvref_t<_Tuple>>
1272         struct _UseOtherCtor
1273         : false_type
1274         { };
1275       // If TUPLE is convertible to the single element in *this,
1276       // then TUPLE should match tuple(UTypes&&...) instead.
1277       template<typename _Tuple, typename _Tp, typename _Up>
1278         struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>>
1279         : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>::type
1280         { };
1281       // If TUPLE and *this each have a single element of the same type,
1282       // then TUPLE should match a copy/move constructor instead.
1283       template<typename _Tuple, typename _Tp>
1284         struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>>
1285         : true_type
1286         { };
1288       // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
1289       // and the single element in Types can be initialized from TUPLE,
1290       // or is the same type as tuple_element_t<0, TUPLE>.
1291       template<typename _Tuple>
1292         static constexpr bool __use_other_ctor()
1293         { return _UseOtherCtor<_Tuple>::value; }
1295       /// @cond undocumented
1296 #undef __glibcxx_no_dangling_refs
1297 #if __has_builtin(__reference_constructs_from_temporary) \
1298       && defined _GLIBCXX_DEBUG
1299       // Error if construction from U... would create a dangling ref.
1300 # if __cpp_fold_expressions
1301 #  define __glibcxx_dangling_refs(U) \
1302   (__reference_constructs_from_temporary(_Elements, U) && ...)
1303 # else
1304 #  define __glibcxx_dangling_refs(U) \
1305   __or_<__bool_constant<__reference_constructs_from_temporary(_Elements, U) \
1306        >...>::value
1307 # endif
1308 # define __glibcxx_no_dangling_refs(U) \
1309   static_assert(!__glibcxx_dangling_refs(U), \
1310                 "std::tuple constructor creates a dangling reference")
1311 #else
1312 # define __glibcxx_no_dangling_refs(U)
1313 #endif
1314       /// @endcond
1316     public:
1317       template<typename _Dummy = void,
1318                _ImplicitDefaultCtor<is_void<_Dummy>::value> = true>
1319         constexpr
1320         tuple()
1321         noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1322         : _Inherited() { }
1324       template<typename _Dummy = void,
1325                _ExplicitDefaultCtor<is_void<_Dummy>::value> = false>
1326         explicit constexpr
1327         tuple()
1328         noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1329         : _Inherited() { }
1331       template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1332                _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1333         constexpr
1334         tuple(const _Elements&... __elements)
1335         noexcept(__nothrow_constructible<const _Elements&...>())
1336         : _Inherited(__elements...) { }
1338       template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1339                _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1340         explicit constexpr
1341         tuple(const _Elements&... __elements)
1342         noexcept(__nothrow_constructible<const _Elements&...>())
1343         : _Inherited(__elements...) { }
1345       template<typename... _UElements,
1346                bool _Valid = __valid_args<_UElements...>(),
1347                _ImplicitCtor<_Valid, _UElements...> = true>
1348         constexpr
1349         tuple(_UElements&&... __elements)
1350         noexcept(__nothrow_constructible<_UElements...>())
1351         : _Inherited(std::forward<_UElements>(__elements)...)
1352         { __glibcxx_no_dangling_refs(_UElements&&); }
1354       template<typename... _UElements,
1355                bool _Valid = __valid_args<_UElements...>(),
1356                _ExplicitCtor<_Valid, _UElements...> = false>
1357         explicit constexpr
1358         tuple(_UElements&&... __elements)
1359         noexcept(__nothrow_constructible<_UElements...>())
1360         : _Inherited(std::forward<_UElements>(__elements)...)
1361         { __glibcxx_no_dangling_refs(_UElements&&); }
1363       constexpr tuple(const tuple&) = default;
1365       constexpr tuple(tuple&&) = default;
1367       template<typename... _UElements,
1368                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1369                            && !__use_other_ctor<const tuple<_UElements...>&>(),
1370                _ImplicitCtor<_Valid, const _UElements&...> = true>
1371         constexpr
1372         tuple(const tuple<_UElements...>& __in)
1373         noexcept(__nothrow_constructible<const _UElements&...>())
1374         : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1375         { __glibcxx_no_dangling_refs(const _UElements&); }
1377       template<typename... _UElements,
1378                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1379                            && !__use_other_ctor<const tuple<_UElements...>&>(),
1380                _ExplicitCtor<_Valid, const _UElements&...> = false>
1381         explicit constexpr
1382         tuple(const tuple<_UElements...>& __in)
1383         noexcept(__nothrow_constructible<const _UElements&...>())
1384         : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1385         { __glibcxx_no_dangling_refs(const _UElements&); }
1387       template<typename... _UElements,
1388                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1389                              && !__use_other_ctor<tuple<_UElements...>&&>(),
1390                _ImplicitCtor<_Valid, _UElements...> = true>
1391         constexpr
1392         tuple(tuple<_UElements...>&& __in)
1393         noexcept(__nothrow_constructible<_UElements...>())
1394         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1395         { __glibcxx_no_dangling_refs(_UElements&&); }
1397       template<typename... _UElements,
1398                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1399                              && !__use_other_ctor<tuple<_UElements...>&&>(),
1400                _ExplicitCtor<_Valid, _UElements...> = false>
1401         explicit constexpr
1402         tuple(tuple<_UElements...>&& __in)
1403         noexcept(__nothrow_constructible<_UElements...>())
1404         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1405         { __glibcxx_no_dangling_refs(_UElements&&); }
1407       // Allocator-extended constructors.
1409       template<typename _Alloc,
1410                _ImplicitDefaultCtor<is_object<_Alloc>::value> = true>
1411         _GLIBCXX20_CONSTEXPR
1412         tuple(allocator_arg_t __tag, const _Alloc& __a)
1413         : _Inherited(__tag, __a) { }
1415       template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1416                _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1417         _GLIBCXX20_CONSTEXPR
1418         tuple(allocator_arg_t __tag, const _Alloc& __a,
1419               const _Elements&... __elements)
1420         : _Inherited(__tag, __a, __elements...) { }
1422       template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1423                _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1424         _GLIBCXX20_CONSTEXPR
1425         explicit
1426         tuple(allocator_arg_t __tag, const _Alloc& __a,
1427               const _Elements&... __elements)
1428         : _Inherited(__tag, __a, __elements...) { }
1430       template<typename _Alloc, typename... _UElements,
1431                bool _Valid = __valid_args<_UElements...>(),
1432                _ImplicitCtor<_Valid, _UElements...> = true>
1433         _GLIBCXX20_CONSTEXPR
1434         tuple(allocator_arg_t __tag, const _Alloc& __a,
1435               _UElements&&... __elements)
1436         : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1437         { __glibcxx_no_dangling_refs(_UElements&&); }
1439       template<typename _Alloc, typename... _UElements,
1440                  bool _Valid = __valid_args<_UElements...>(),
1441                _ExplicitCtor<_Valid, _UElements...> = false>
1442         _GLIBCXX20_CONSTEXPR
1443         explicit
1444         tuple(allocator_arg_t __tag, const _Alloc& __a,
1445               _UElements&&... __elements)
1446         : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1447         { __glibcxx_no_dangling_refs(_UElements&&); }
1449       template<typename _Alloc>
1450         _GLIBCXX20_CONSTEXPR
1451         tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1452         : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1454       template<typename _Alloc>
1455         _GLIBCXX20_CONSTEXPR
1456         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1457         : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1459       template<typename _Alloc, typename... _UElements,
1460                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1461                              && !__use_other_ctor<const tuple<_UElements...>&>(),
1462                _ImplicitCtor<_Valid, const _UElements&...> = true>
1463         _GLIBCXX20_CONSTEXPR
1464         tuple(allocator_arg_t __tag, const _Alloc& __a,
1465               const tuple<_UElements...>& __in)
1466         : _Inherited(__tag, __a,
1467                      static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1468         { __glibcxx_no_dangling_refs(const _UElements&); }
1470       template<typename _Alloc, typename... _UElements,
1471                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1472                              && !__use_other_ctor<const tuple<_UElements...>&>(),
1473                _ExplicitCtor<_Valid, const _UElements&...> = false>
1474         _GLIBCXX20_CONSTEXPR
1475         explicit
1476         tuple(allocator_arg_t __tag, const _Alloc& __a,
1477               const tuple<_UElements...>& __in)
1478         : _Inherited(__tag, __a,
1479                      static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1480         { __glibcxx_no_dangling_refs(const _UElements&); }
1482       template<typename _Alloc, typename... _UElements,
1483                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1484                              && !__use_other_ctor<tuple<_UElements...>&&>(),
1485                _ImplicitCtor<_Valid, _UElements...> = true>
1486         _GLIBCXX20_CONSTEXPR
1487         tuple(allocator_arg_t __tag, const _Alloc& __a,
1488               tuple<_UElements...>&& __in)
1489         : _Inherited(__tag, __a,
1490                      static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1491         { __glibcxx_no_dangling_refs(_UElements&&); }
1493       template<typename _Alloc, typename... _UElements,
1494                bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1495                              && !__use_other_ctor<tuple<_UElements...>&&>(),
1496                _ExplicitCtor<_Valid, _UElements...> = false>
1497         _GLIBCXX20_CONSTEXPR
1498         explicit
1499         tuple(allocator_arg_t __tag, const _Alloc& __a,
1500               tuple<_UElements...>&& __in)
1501         : _Inherited(__tag, __a,
1502                      static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1503         { __glibcxx_no_dangling_refs(_UElements&&); }
1504 #endif // concepts && conditional_explicit
1506       // tuple assignment
1508 #if __cpp_concepts && __cpp_consteval // >= C++20
1509     private:
1510       template<typename... _UTypes>
1511         static consteval bool
1512         __assignable()
1513         {
1514           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1515             return __and_v<is_assignable<_Elements&, _UTypes>...>;
1516           else
1517             return false;
1518         }
1520       template<typename... _UTypes>
1521         static consteval bool
1522         __nothrow_assignable()
1523         {
1524           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1525             return __and_v<is_nothrow_assignable<_Elements&, _UTypes>...>;
1526           else
1527             return false;
1528         }
1530 #if __cpp_lib_ranges_zip // >= C++23
1531       template<typename... _UTypes>
1532         static consteval bool
1533         __const_assignable()
1534         {
1535           if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1536             return __and_v<is_assignable<const _Elements&, _UTypes>...>;
1537           else
1538             return false;
1539         }
1540 #endif // C++23
1542     public:
1544       tuple& operator=(const tuple& __u) = delete;
1546       constexpr tuple&
1547       operator=(const tuple& __u)
1548       noexcept(__nothrow_assignable<const _Elements&...>())
1549       requires (__assignable<const _Elements&...>())
1550       {
1551         this->_M_assign(__u);
1552         return *this;
1553       }
1555       constexpr tuple&
1556       operator=(tuple&& __u)
1557       noexcept(__nothrow_assignable<_Elements...>())
1558       requires (__assignable<_Elements...>())
1559       {
1560         this->_M_assign(std::move(__u));
1561         return *this;
1562       }
1564       template<typename... _UTypes>
1565         requires (__assignable<const _UTypes&...>())
1566         constexpr tuple&
1567         operator=(const tuple<_UTypes...>& __u)
1568         noexcept(__nothrow_assignable<const _UTypes&...>())
1569         {
1570           this->_M_assign(__u);
1571           return *this;
1572         }
1574       template<typename... _UTypes>
1575         requires (__assignable<_UTypes...>())
1576         constexpr tuple&
1577         operator=(tuple<_UTypes...>&& __u)
1578         noexcept(__nothrow_assignable<_UTypes...>())
1579         {
1580           this->_M_assign(std::move(__u));
1581           return *this;
1582         }
1584 #if __cpp_lib_ranges_zip // >= C++23
1585       constexpr const tuple&
1586       operator=(const tuple& __u) const
1587       requires (__const_assignable<const _Elements&...>())
1588       {
1589         this->_M_assign(__u);
1590         return *this;
1591       }
1593       constexpr const tuple&
1594       operator=(tuple&& __u) const
1595       requires (__const_assignable<_Elements...>())
1596       {
1597         this->_M_assign(std::move(__u));
1598         return *this;
1599       }
1601       template<typename... _UTypes>
1602         constexpr const tuple&
1603         operator=(const tuple<_UTypes...>& __u) const
1604         requires (__const_assignable<const _UTypes&...>())
1605         {
1606           this->_M_assign(__u);
1607           return *this;
1608         }
1610       template<typename... _UTypes>
1611         constexpr const tuple&
1612         operator=(tuple<_UTypes...>&& __u) const
1613         requires (__const_assignable<_UTypes...>())
1614         {
1615           this->_M_assign(std::move(__u));
1616           return *this;
1617         }
1618 #endif // C++23
1620       template<typename _U1, typename _U2>
1621         requires (__assignable<const _U1&, const _U2&>())
1622         constexpr tuple&
1623         operator=(const pair<_U1, _U2>& __u)
1624         noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1625         {
1626           this->_M_head(*this) = __u.first;
1627           this->_M_tail(*this)._M_head(*this) = __u.second;
1628           return *this;
1629         }
1631       template<typename _U1, typename _U2>
1632         requires (__assignable<_U1, _U2>())
1633         constexpr tuple&
1634         operator=(pair<_U1, _U2>&& __u)
1635         noexcept(__nothrow_assignable<_U1, _U2>())
1636         {
1637           this->_M_head(*this) = std::forward<_U1>(__u.first);
1638           this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1639           return *this;
1640         }
1642 #if __cpp_lib_ranges_zip // >= C++23
1643       template<typename _U1, typename _U2>
1644         requires (__const_assignable<const _U1&, const _U2>())
1645         constexpr const tuple&
1646         operator=(const pair<_U1, _U2>& __u) const
1647         {
1648           this->_M_head(*this) = __u.first;
1649           this->_M_tail(*this)._M_head(*this) = __u.second;
1650           return *this;
1651         }
1653       template<typename _U1, typename _U2>
1654         requires (__const_assignable<_U1, _U2>())
1655         constexpr const tuple&
1656         operator=(pair<_U1, _U2>&& __u) const
1657         {
1658           this->_M_head(*this) = std::forward<_U1>(__u.first);
1659           this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1660           return *this;
1661         }
1662 #endif // C++23
1664 #if 0 && __cpp_lib_tuple_like // >= C++23
1665       template<__tuple_like _UTuple>
1666         constexpr tuple&
1667         operator=(_UTuple&& __u);
1669       template<__tuple_like _UTuple>
1670         constexpr tuple&
1671         operator=(_UTuple&& __u) const;
1672 #endif // C++23
1674 #else // ! (concepts && consteval)
1676     private:
1677       template<typename... _UElements>
1678         static constexpr
1679         __enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
1680         __assignable()
1681         { return __and_<is_assignable<_Elements&, _UElements>...>::value; }
1683       // Condition for noexcept-specifier of an assignment operator.
1684       template<typename... _UElements>
1685         static constexpr bool __nothrow_assignable()
1686         {
1687           return
1688             __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
1689         }
1691     public:
1693       _GLIBCXX20_CONSTEXPR
1694       tuple&
1695       operator=(__conditional_t<__assignable<const _Elements&...>(),
1696                                 const tuple&,
1697                                 const __nonesuch&> __in)
1698       noexcept(__nothrow_assignable<const _Elements&...>())
1699       {
1700         this->_M_assign(__in);
1701         return *this;
1702       }
1704       _GLIBCXX20_CONSTEXPR
1705       tuple&
1706       operator=(__conditional_t<__assignable<_Elements...>(),
1707                                 tuple&&,
1708                                 __nonesuch&&> __in)
1709       noexcept(__nothrow_assignable<_Elements...>())
1710       {
1711         this->_M_assign(std::move(__in));
1712         return *this;
1713       }
1715       template<typename... _UElements>
1716         _GLIBCXX20_CONSTEXPR
1717         __enable_if_t<__assignable<const _UElements&...>(), tuple&>
1718         operator=(const tuple<_UElements...>& __in)
1719         noexcept(__nothrow_assignable<const _UElements&...>())
1720         {
1721           this->_M_assign(__in);
1722           return *this;
1723         }
1725       template<typename... _UElements>
1726         _GLIBCXX20_CONSTEXPR
1727         __enable_if_t<__assignable<_UElements...>(), tuple&>
1728         operator=(tuple<_UElements...>&& __in)
1729         noexcept(__nothrow_assignable<_UElements...>())
1730         {
1731           this->_M_assign(std::move(__in));
1732           return *this;
1733         }
1734 #endif // concepts && consteval
1736       // tuple swap
1737       _GLIBCXX20_CONSTEXPR
1738       void
1739       swap(tuple& __in)
1740       noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
1741       { _Inherited::_M_swap(__in); }
1743 #if __cpp_lib_ranges_zip // >= C++23
1744       // As an extension, we constrain the const swap member function in order
1745       // to continue accepting explicit instantiation of tuples whose elements
1746       // are not all const swappable.  Without this constraint, such an
1747       // explicit instantiation would also instantiate the ill-formed body of
1748       // this function and yield a hard error.  This constraint shouldn't
1749       // affect the behavior of valid programs.
1750       constexpr void
1751       swap(const tuple& __in) const
1752       noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
1753       requires (is_swappable_v<const _Elements> && ...)
1754       { _Inherited::_M_swap(__in); }
1755 #endif // C++23
1756     };
1758 #if __cpp_deduction_guides >= 201606
1759   template<typename... _UTypes>
1760     tuple(_UTypes...) -> tuple<_UTypes...>;
1761   template<typename _T1, typename _T2>
1762     tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
1763   template<typename _Alloc, typename... _UTypes>
1764     tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
1765   template<typename _Alloc, typename _T1, typename _T2>
1766     tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
1767   template<typename _Alloc, typename... _UTypes>
1768     tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
1769 #endif
1771   // Explicit specialization, zero-element tuple.
1772   template<>
1773     class tuple<>
1774     {
1775     public:
1776       _GLIBCXX20_CONSTEXPR
1777       void swap(tuple&) noexcept { /* no-op */ }
1778 #if __cpp_lib_ranges_zip // >= C++23
1779       constexpr void swap(const tuple&) const noexcept { /* no-op */ }
1780 #endif
1781       // We need the default since we're going to define no-op
1782       // allocator constructors.
1783       tuple() = default;
1784       // No-op allocator constructors.
1785       template<typename _Alloc>
1786         _GLIBCXX20_CONSTEXPR
1787         tuple(allocator_arg_t, const _Alloc&) noexcept { }
1788       template<typename _Alloc>
1789         _GLIBCXX20_CONSTEXPR
1790         tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
1791     };
1793 #if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20
1794   /// Partial specialization, 2-element tuple.
1795   /// Includes construction and assignment from a pair.
1796   template<typename _T1, typename _T2>
1797     class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
1798     {
1799       typedef _Tuple_impl<0, _T1, _T2> _Inherited;
1801       // Constraint for non-explicit default constructor
1802       template<bool _Dummy, typename _U1, typename _U2>
1803         using _ImplicitDefaultCtor = __enable_if_t<
1804           _TupleConstraints<_Dummy, _U1, _U2>::
1805             __is_implicitly_default_constructible(),
1806           bool>;
1808       // Constraint for explicit default constructor
1809       template<bool _Dummy, typename _U1, typename _U2>
1810         using _ExplicitDefaultCtor = __enable_if_t<
1811           _TupleConstraints<_Dummy, _U1, _U2>::
1812             __is_explicitly_default_constructible(),
1813           bool>;
1815       template<bool _Dummy>
1816         using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
1818       // Constraint for non-explicit constructors
1819       template<bool _Cond, typename _U1, typename _U2>
1820         using _ImplicitCtor = __enable_if_t<
1821           _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
1822           bool>;
1824       // Constraint for non-explicit constructors
1825       template<bool _Cond, typename _U1, typename _U2>
1826         using _ExplicitCtor = __enable_if_t<
1827           _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
1828           bool>;
1830       template<typename _U1, typename _U2>
1831         static constexpr bool __assignable()
1832         {
1833           return __and_<is_assignable<_T1&, _U1>,
1834                         is_assignable<_T2&, _U2>>::value;
1835         }
1837       template<typename _U1, typename _U2>
1838         static constexpr bool __nothrow_assignable()
1839         {
1840           return __and_<is_nothrow_assignable<_T1&, _U1>,
1841                         is_nothrow_assignable<_T2&, _U2>>::value;
1842         }
1844       template<typename _U1, typename _U2>
1845         static constexpr bool __nothrow_constructible()
1846         {
1847           return __and_<is_nothrow_constructible<_T1, _U1>,
1848                             is_nothrow_constructible<_T2, _U2>>::value;
1849         }
1851       static constexpr bool __nothrow_default_constructible()
1852       {
1853         return __and_<is_nothrow_default_constructible<_T1>,
1854                       is_nothrow_default_constructible<_T2>>::value;
1855       }
1857       template<typename _U1>
1858         static constexpr bool __is_alloc_arg()
1859         { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
1861       /// @cond undocumented
1862 #undef __glibcxx_no_dangling_refs
1863       // Error if construction from _U1 and _U2 would create a dangling ref.
1864 #if __has_builtin(__reference_constructs_from_temporary) \
1865       && defined _GLIBCXX_DEBUG
1866 # define __glibcxx_no_dangling_refs(_U1, _U2) \
1867   static_assert(!__reference_constructs_from_temporary(_T1, _U1) \
1868                && !__reference_constructs_from_temporary(_T2, _U2), \
1869                 "std::tuple constructor creates a dangling reference")
1870 #else
1871 # define __glibcxx_no_dangling_refs(_U1, _U2)
1872 #endif
1873       /// @endcond
1875     public:
1876       template<bool _Dummy = true,
1877                _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
1878         constexpr
1879         tuple()
1880         noexcept(__nothrow_default_constructible())
1881         : _Inherited() { }
1883       template<bool _Dummy = true,
1884                _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
1885         explicit constexpr
1886         tuple()
1887         noexcept(__nothrow_default_constructible())
1888         : _Inherited() { }
1890       template<bool _Dummy = true,
1891                _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
1892         constexpr
1893         tuple(const _T1& __a1, const _T2& __a2)
1894         noexcept(__nothrow_constructible<const _T1&, const _T2&>())
1895         : _Inherited(__a1, __a2) { }
1897       template<bool _Dummy = true,
1898                _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
1899         explicit constexpr
1900         tuple(const _T1& __a1, const _T2& __a2)
1901         noexcept(__nothrow_constructible<const _T1&, const _T2&>())
1902         : _Inherited(__a1, __a2) { }
1904       template<typename _U1, typename _U2,
1905                _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
1906         constexpr
1907         tuple(_U1&& __a1, _U2&& __a2)
1908         noexcept(__nothrow_constructible<_U1, _U2>())
1909         : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
1910         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
1912       template<typename _U1, typename _U2,
1913                _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
1914         explicit constexpr
1915         tuple(_U1&& __a1, _U2&& __a2)
1916         noexcept(__nothrow_constructible<_U1, _U2>())
1917         : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
1918         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
1920       constexpr tuple(const tuple&) = default;
1922       constexpr tuple(tuple&&) = default;
1924       template<typename _U1, typename _U2,
1925                _ImplicitCtor<true, const _U1&, const _U2&> = true>
1926         constexpr
1927         tuple(const tuple<_U1, _U2>& __in)
1928         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1929         : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
1930         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
1932       template<typename _U1, typename _U2,
1933                _ExplicitCtor<true, const _U1&, const _U2&> = false>
1934         explicit constexpr
1935         tuple(const tuple<_U1, _U2>& __in)
1936         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1937         : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
1938         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
1940       template<typename _U1, typename _U2,
1941                _ImplicitCtor<true, _U1, _U2> = true>
1942         constexpr
1943         tuple(tuple<_U1, _U2>&& __in)
1944         noexcept(__nothrow_constructible<_U1, _U2>())
1945         : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
1946         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
1948       template<typename _U1, typename _U2,
1949                _ExplicitCtor<true, _U1, _U2> = false>
1950         explicit constexpr
1951         tuple(tuple<_U1, _U2>&& __in)
1952         noexcept(__nothrow_constructible<_U1, _U2>())
1953         : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
1954         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
1956       template<typename _U1, typename _U2,
1957                _ImplicitCtor<true, const _U1&, const _U2&> = true>
1958         constexpr
1959         tuple(const pair<_U1, _U2>& __in)
1960         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1961         : _Inherited(__in.first, __in.second)
1962         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
1964       template<typename _U1, typename _U2,
1965                _ExplicitCtor<true, const _U1&, const _U2&> = false>
1966         explicit constexpr
1967         tuple(const pair<_U1, _U2>& __in)
1968         noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1969         : _Inherited(__in.first, __in.second)
1970         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
1972       template<typename _U1, typename _U2,
1973                _ImplicitCtor<true, _U1, _U2> = true>
1974         constexpr
1975         tuple(pair<_U1, _U2>&& __in)
1976         noexcept(__nothrow_constructible<_U1, _U2>())
1977         : _Inherited(std::forward<_U1>(__in.first),
1978                      std::forward<_U2>(__in.second))
1979         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
1981       template<typename _U1, typename _U2,
1982                _ExplicitCtor<true, _U1, _U2> = false>
1983         explicit constexpr
1984         tuple(pair<_U1, _U2>&& __in)
1985         noexcept(__nothrow_constructible<_U1, _U2>())
1986         : _Inherited(std::forward<_U1>(__in.first),
1987                      std::forward<_U2>(__in.second))
1988         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
1990       // Allocator-extended constructors.
1992       template<typename _Alloc,
1993                _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
1994         _GLIBCXX20_CONSTEXPR
1995         tuple(allocator_arg_t __tag, const _Alloc& __a)
1996         : _Inherited(__tag, __a) { }
1998       template<typename _Alloc, bool _Dummy = true,
1999                _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2000         _GLIBCXX20_CONSTEXPR
2001         tuple(allocator_arg_t __tag, const _Alloc& __a,
2002               const _T1& __a1, const _T2& __a2)
2003         : _Inherited(__tag, __a, __a1, __a2) { }
2005       template<typename _Alloc, bool _Dummy = true,
2006                _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2007         explicit
2008         _GLIBCXX20_CONSTEXPR
2009         tuple(allocator_arg_t __tag, const _Alloc& __a,
2010               const _T1& __a1, const _T2& __a2)
2011         : _Inherited(__tag, __a, __a1, __a2) { }
2013       template<typename _Alloc, typename _U1, typename _U2,
2014                _ImplicitCtor<true, _U1, _U2> = true>
2015         _GLIBCXX20_CONSTEXPR
2016         tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
2017         : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2018                      std::forward<_U2>(__a2))
2019         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2021       template<typename _Alloc, typename _U1, typename _U2,
2022                _ExplicitCtor<true, _U1, _U2> = false>
2023         explicit
2024         _GLIBCXX20_CONSTEXPR
2025         tuple(allocator_arg_t __tag, const _Alloc& __a,
2026               _U1&& __a1, _U2&& __a2)
2027         : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2028                      std::forward<_U2>(__a2))
2029         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2031       template<typename _Alloc>
2032         _GLIBCXX20_CONSTEXPR
2033         tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
2034         : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
2036       template<typename _Alloc>
2037         _GLIBCXX20_CONSTEXPR
2038         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
2039         : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
2041       template<typename _Alloc, typename _U1, typename _U2,
2042                _ImplicitCtor<true, const _U1&, const _U2&> = true>
2043         _GLIBCXX20_CONSTEXPR
2044         tuple(allocator_arg_t __tag, const _Alloc& __a,
2045               const tuple<_U1, _U2>& __in)
2046         : _Inherited(__tag, __a,
2047                      static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2048         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2050       template<typename _Alloc, typename _U1, typename _U2,
2051                _ExplicitCtor<true, const _U1&, const _U2&> = false>
2052         explicit
2053         _GLIBCXX20_CONSTEXPR
2054         tuple(allocator_arg_t __tag, const _Alloc& __a,
2055               const tuple<_U1, _U2>& __in)
2056         : _Inherited(__tag, __a,
2057                      static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2058         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2060       template<typename _Alloc, typename _U1, typename _U2,
2061                _ImplicitCtor<true, _U1, _U2> = true>
2062         _GLIBCXX20_CONSTEXPR
2063         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2064         : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2065         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2067       template<typename _Alloc, typename _U1, typename _U2,
2068                _ExplicitCtor<true, _U1, _U2> = false>
2069         explicit
2070         _GLIBCXX20_CONSTEXPR
2071         tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2072         : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2073         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2075       template<typename _Alloc, typename _U1, typename _U2,
2076                _ImplicitCtor<true, const _U1&, const _U2&> = true>
2077         _GLIBCXX20_CONSTEXPR
2078         tuple(allocator_arg_t __tag, const _Alloc& __a,
2079               const pair<_U1, _U2>& __in)
2080         : _Inherited(__tag, __a, __in.first, __in.second)
2081         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2083       template<typename _Alloc, typename _U1, typename _U2,
2084                _ExplicitCtor<true, const _U1&, const _U2&> = false>
2085         explicit
2086         _GLIBCXX20_CONSTEXPR
2087         tuple(allocator_arg_t __tag, const _Alloc& __a,
2088               const pair<_U1, _U2>& __in)
2089         : _Inherited(__tag, __a, __in.first, __in.second)
2090         { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2092       template<typename _Alloc, typename _U1, typename _U2,
2093                _ImplicitCtor<true, _U1, _U2> = true>
2094         _GLIBCXX20_CONSTEXPR
2095         tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2096         : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2097                      std::forward<_U2>(__in.second))
2098         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2100       template<typename _Alloc, typename _U1, typename _U2,
2101                _ExplicitCtor<true, _U1, _U2> = false>
2102         explicit
2103         _GLIBCXX20_CONSTEXPR
2104         tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2105         : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2106                      std::forward<_U2>(__in.second))
2107         { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2109       // Tuple assignment.
2111       _GLIBCXX20_CONSTEXPR
2112       tuple&
2113       operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
2114                                 const tuple&,
2115                                 const __nonesuch&> __in)
2116       noexcept(__nothrow_assignable<const _T1&, const _T2&>())
2117       {
2118         this->_M_assign(__in);
2119         return *this;
2120       }
2122       _GLIBCXX20_CONSTEXPR
2123       tuple&
2124       operator=(__conditional_t<__assignable<_T1, _T2>(),
2125                                 tuple&&,
2126                                 __nonesuch&&> __in)
2127       noexcept(__nothrow_assignable<_T1, _T2>())
2128       {
2129         this->_M_assign(std::move(__in));
2130         return *this;
2131       }
2133       template<typename _U1, typename _U2>
2134         _GLIBCXX20_CONSTEXPR
2135         __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2136         operator=(const tuple<_U1, _U2>& __in)
2137         noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2138         {
2139           this->_M_assign(__in);
2140           return *this;
2141         }
2143       template<typename _U1, typename _U2>
2144         _GLIBCXX20_CONSTEXPR
2145         __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2146         operator=(tuple<_U1, _U2>&& __in)
2147         noexcept(__nothrow_assignable<_U1, _U2>())
2148         {
2149           this->_M_assign(std::move(__in));
2150           return *this;
2151         }
2153       template<typename _U1, typename _U2>
2154         _GLIBCXX20_CONSTEXPR
2155         __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2156         operator=(const pair<_U1, _U2>& __in)
2157         noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2158         {
2159           this->_M_head(*this) = __in.first;
2160           this->_M_tail(*this)._M_head(*this) = __in.second;
2161           return *this;
2162         }
2164       template<typename _U1, typename _U2>
2165         _GLIBCXX20_CONSTEXPR
2166         __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2167         operator=(pair<_U1, _U2>&& __in)
2168         noexcept(__nothrow_assignable<_U1, _U2>())
2169         {
2170           this->_M_head(*this) = std::forward<_U1>(__in.first);
2171           this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
2172           return *this;
2173         }
2175       _GLIBCXX20_CONSTEXPR
2176       void
2177       swap(tuple& __in)
2178       noexcept(__and_<__is_nothrow_swappable<_T1>,
2179                       __is_nothrow_swappable<_T2>>::value)
2180       { _Inherited::_M_swap(__in); }
2181     };
2182 #endif // concepts && conditional_explicit
2184   /// class tuple_size
2185   template<typename... _Elements>
2186     struct tuple_size<tuple<_Elements...>>
2187     : public integral_constant<size_t, sizeof...(_Elements)> { };
2189 #if __cplusplus >= 201703L
2190   template<typename... _Types>
2191     inline constexpr size_t tuple_size_v<tuple<_Types...>>
2192       = sizeof...(_Types);
2194   template<typename... _Types>
2195     inline constexpr size_t tuple_size_v<const tuple<_Types...>>
2196       = sizeof...(_Types);
2197 #endif
2199   /// Trait to get the Ith element type from a tuple.
2200   template<size_t __i, typename... _Types>
2201     struct tuple_element<__i, tuple<_Types...>>
2202     {
2203       static_assert(__i < sizeof...(_Types), "tuple index must be in range");
2205       using type = typename _Nth_type<__i, _Types...>::type;
2206     };
2208   template<size_t __i, typename _Head, typename... _Tail>
2209     constexpr _Head&
2210     __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2211     { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2213   template<size_t __i, typename _Head, typename... _Tail>
2214     constexpr const _Head&
2215     __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2216     { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2218   // Deleted overload to improve diagnostics for invalid indices
2219   template<size_t __i, typename... _Types>
2220     __enable_if_t<(__i >= sizeof...(_Types))>
2221     __get_helper(const tuple<_Types...>&) = delete;
2223   /// Return a reference to the ith element of a tuple.
2224   template<size_t __i, typename... _Elements>
2225     constexpr __tuple_element_t<__i, tuple<_Elements...>>&
2226     get(tuple<_Elements...>& __t) noexcept
2227     { return std::__get_helper<__i>(__t); }
2229   /// Return a const reference to the ith element of a const tuple.
2230   template<size_t __i, typename... _Elements>
2231     constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
2232     get(const tuple<_Elements...>& __t) noexcept
2233     { return std::__get_helper<__i>(__t); }
2235   /// Return an rvalue reference to the ith element of a tuple rvalue.
2236   template<size_t __i, typename... _Elements>
2237     constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
2238     get(tuple<_Elements...>&& __t) noexcept
2239     {
2240       typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2241       return std::forward<__element_type>(std::__get_helper<__i>(__t));
2242     }
2244   /// Return a const rvalue reference to the ith element of a const tuple rvalue.
2245   template<size_t __i, typename... _Elements>
2246     constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
2247     get(const tuple<_Elements...>&& __t) noexcept
2248     {
2249       typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2250       return std::forward<const __element_type>(std::__get_helper<__i>(__t));
2251     }
2253   /// @cond undocumented
2254   // Deleted overload chosen for invalid indices.
2255   template<size_t __i, typename... _Elements>
2256     constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
2257     get(const tuple<_Elements...>&) = delete;
2258   /// @endcond
2260 #ifdef __cpp_lib_tuples_by_type // C++ >= 14
2261   /// Return a reference to the unique element of type _Tp of a tuple.
2262   template <typename _Tp, typename... _Types>
2263     constexpr _Tp&
2264     get(tuple<_Types...>& __t) noexcept
2265     {
2266       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2267       static_assert(__idx < sizeof...(_Types),
2268           "the type T in std::get<T> must occur exactly once in the tuple");
2269       return std::__get_helper<__idx>(__t);
2270     }
2272   /// Return a reference to the unique element of type _Tp of a tuple rvalue.
2273   template <typename _Tp, typename... _Types>
2274     constexpr _Tp&&
2275     get(tuple<_Types...>&& __t) noexcept
2276     {
2277       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2278       static_assert(__idx < sizeof...(_Types),
2279           "the type T in std::get<T> must occur exactly once in the tuple");
2280       return std::forward<_Tp>(std::__get_helper<__idx>(__t));
2281     }
2283   /// Return a const reference to the unique element of type _Tp of a tuple.
2284   template <typename _Tp, typename... _Types>
2285     constexpr const _Tp&
2286     get(const tuple<_Types...>& __t) noexcept
2287     {
2288       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2289       static_assert(__idx < sizeof...(_Types),
2290           "the type T in std::get<T> must occur exactly once in the tuple");
2291       return std::__get_helper<__idx>(__t);
2292     }
2294   /// Return a const reference to the unique element of type _Tp of
2295   /// a const tuple rvalue.
2296   template <typename _Tp, typename... _Types>
2297     constexpr const _Tp&&
2298     get(const tuple<_Types...>&& __t) noexcept
2299     {
2300       constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2301       static_assert(__idx < sizeof...(_Types),
2302           "the type T in std::get<T> must occur exactly once in the tuple");
2303       return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
2304     }
2305 #endif
2307   // This class performs the comparison operations on tuples
2308   template<typename _Tp, typename _Up, size_t __i, size_t __size>
2309     struct __tuple_compare
2310     {
2311       static constexpr bool
2312       __eq(const _Tp& __t, const _Up& __u)
2313       {
2314         return bool(std::get<__i>(__t) == std::get<__i>(__u))
2315           && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
2316       }
2318       static constexpr bool
2319       __less(const _Tp& __t, const _Up& __u)
2320       {
2321         return bool(std::get<__i>(__t) < std::get<__i>(__u))
2322           || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
2323               && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
2324       }
2325     };
2327   template<typename _Tp, typename _Up, size_t __size>
2328     struct __tuple_compare<_Tp, _Up, __size, __size>
2329     {
2330       static constexpr bool
2331       __eq(const _Tp&, const _Up&) { return true; }
2333       static constexpr bool
2334       __less(const _Tp&, const _Up&) { return false; }
2335     };
2337   template<typename... _TElements, typename... _UElements>
2338     constexpr bool
2339     operator==(const tuple<_TElements...>& __t,
2340                const tuple<_UElements...>& __u)
2341     {
2342       static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2343           "tuple objects can only be compared if they have equal sizes.");
2344       using __compare = __tuple_compare<tuple<_TElements...>,
2345                                         tuple<_UElements...>,
2346                                         0, sizeof...(_TElements)>;
2347       return __compare::__eq(__t, __u);
2348     }
2350 #if __cpp_lib_three_way_comparison
2351   template<typename _Cat, typename _Tp, typename _Up>
2352     constexpr _Cat
2353     __tuple_cmp(const _Tp&, const _Up&, index_sequence<>)
2354     { return _Cat::equivalent; }
2356   template<typename _Cat, typename _Tp, typename _Up,
2357            size_t _Idx0, size_t... _Idxs>
2358     constexpr _Cat
2359     __tuple_cmp(const _Tp& __t, const _Up& __u,
2360                 index_sequence<_Idx0, _Idxs...>)
2361     {
2362       auto __c
2363         = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u));
2364       if (__c != 0)
2365         return __c;
2366       return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>());
2367     }
2369   template<typename... _Tps, typename... _Ups>
2370     constexpr
2371     common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
2372     operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
2373     {
2374       using _Cat
2375         = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
2376       return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
2377     }
2378 #else
2379   template<typename... _TElements, typename... _UElements>
2380     constexpr bool
2381     operator<(const tuple<_TElements...>& __t,
2382               const tuple<_UElements...>& __u)
2383     {
2384       static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2385           "tuple objects can only be compared if they have equal sizes.");
2386       using __compare = __tuple_compare<tuple<_TElements...>,
2387                                         tuple<_UElements...>,
2388                                         0, sizeof...(_TElements)>;
2389       return __compare::__less(__t, __u);
2390     }
2392   template<typename... _TElements, typename... _UElements>
2393     constexpr bool
2394     operator!=(const tuple<_TElements...>& __t,
2395                const tuple<_UElements...>& __u)
2396     { return !(__t == __u); }
2398   template<typename... _TElements, typename... _UElements>
2399     constexpr bool
2400     operator>(const tuple<_TElements...>& __t,
2401               const tuple<_UElements...>& __u)
2402     { return __u < __t; }
2404   template<typename... _TElements, typename... _UElements>
2405     constexpr bool
2406     operator<=(const tuple<_TElements...>& __t,
2407                const tuple<_UElements...>& __u)
2408     { return !(__u < __t); }
2410   template<typename... _TElements, typename... _UElements>
2411     constexpr bool
2412     operator>=(const tuple<_TElements...>& __t,
2413                const tuple<_UElements...>& __u)
2414     { return !(__t < __u); }
2415 #endif // three_way_comparison
2417   // NB: DR 705.
2418   /// Create a tuple containing copies of the arguments
2419   template<typename... _Elements>
2420     constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
2421     make_tuple(_Elements&&... __args)
2422     {
2423       typedef tuple<typename __decay_and_strip<_Elements>::__type...>
2424         __result_type;
2425       return __result_type(std::forward<_Elements>(__args)...);
2426     }
2428   // _GLIBCXX_RESOLVE_LIB_DEFECTS
2429   // 2275. Why is forward_as_tuple not constexpr?
2430   /// Create a tuple of lvalue or rvalue references to the arguments
2431   template<typename... _Elements>
2432     constexpr tuple<_Elements&&...>
2433     forward_as_tuple(_Elements&&... __args) noexcept
2434     { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2436   // Declarations of std::array and its std::get overloads, so that
2437   // std::tuple_cat can use them if <tuple> is included before <array>.
2439   template<typename _Tp, size_t _Nm> struct array;
2441   template<size_t _Int, typename _Tp, size_t _Nm>
2442     constexpr _Tp&
2443     get(array<_Tp, _Nm>&) noexcept;
2445   template<size_t _Int, typename _Tp, size_t _Nm>
2446     constexpr _Tp&&
2447     get(array<_Tp, _Nm>&&) noexcept;
2449   template<size_t _Int, typename _Tp, size_t _Nm>
2450     constexpr const _Tp&
2451     get(const array<_Tp, _Nm>&) noexcept;
2453   template<size_t _Int, typename _Tp, size_t _Nm>
2454     constexpr const _Tp&&
2455     get(const array<_Tp, _Nm>&&) noexcept;
2457   /// @cond undocumented
2458   template<size_t, typename, typename, size_t>
2459     struct __make_tuple_impl;
2461   template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
2462     struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
2463     : __make_tuple_impl<_Idx + 1,
2464                         tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
2465                         _Tuple, _Nm>
2466     { };
2468   template<size_t _Nm, typename _Tuple, typename... _Tp>
2469     struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
2470     {
2471       typedef tuple<_Tp...> __type;
2472     };
2474   template<typename _Tuple>
2475     struct __do_make_tuple
2476     : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
2477     { };
2479   // Returns the std::tuple equivalent of a tuple-like type.
2480   template<typename _Tuple>
2481     struct __make_tuple
2482     : public __do_make_tuple<__remove_cvref_t<_Tuple>>
2483     { };
2485   // Combines several std::tuple's into a single one.
2486   template<typename...>
2487     struct __combine_tuples;
2489   template<>
2490     struct __combine_tuples<>
2491     {
2492       typedef tuple<> __type;
2493     };
2495   template<typename... _Ts>
2496     struct __combine_tuples<tuple<_Ts...>>
2497     {
2498       typedef tuple<_Ts...> __type;
2499     };
2501   template<typename... _T1s, typename... _T2s, typename... _Rem>
2502     struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
2503     {
2504       typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
2505                                         _Rem...>::__type __type;
2506     };
2508   // Computes the result type of tuple_cat given a set of tuple-like types.
2509   template<typename... _Tpls>
2510     struct __tuple_cat_result
2511     {
2512       typedef typename __combine_tuples
2513         <typename __make_tuple<_Tpls>::__type...>::__type __type;
2514     };
2516   // Helper to determine the index set for the first tuple-like
2517   // type of a given set.
2518   template<typename...>
2519     struct __make_1st_indices;
2521   template<>
2522     struct __make_1st_indices<>
2523     {
2524       typedef _Index_tuple<> __type;
2525     };
2527   template<typename _Tp, typename... _Tpls>
2528     struct __make_1st_indices<_Tp, _Tpls...>
2529     {
2530       typedef typename _Build_index_tuple<tuple_size<
2531         typename remove_reference<_Tp>::type>::value>::__type __type;
2532     };
2534   // Performs the actual concatenation by step-wise expanding tuple-like
2535   // objects into the elements,  which are finally forwarded into the
2536   // result tuple.
2537   template<typename _Ret, typename _Indices, typename... _Tpls>
2538     struct __tuple_concater;
2540   template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2541     struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2542     {
2543       template<typename... _Us>
2544         static constexpr _Ret
2545         _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2546         {
2547           typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2548           typedef __tuple_concater<_Ret, __idx, _Tpls...>      __next;
2549           return __next::_S_do(std::forward<_Tpls>(__tps)...,
2550                                std::forward<_Us>(__us)...,
2551                                std::get<_Is>(std::forward<_Tp>(__tp))...);
2552         }
2553     };
2555   template<typename _Ret>
2556     struct __tuple_concater<_Ret, _Index_tuple<>>
2557     {
2558       template<typename... _Us>
2559         static constexpr _Ret
2560         _S_do(_Us&&... __us)
2561         {
2562           return _Ret(std::forward<_Us>(__us)...);
2563         }
2564     };
2566   template<typename... _Tps>
2567     struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2568     { };
2569   /// @endcond
2571   /// Create a `tuple` containing all elements from multiple tuple-like objects
2572   template<typename... _Tpls, typename = typename
2573            enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2574     constexpr auto
2575     tuple_cat(_Tpls&&... __tpls)
2576     -> typename __tuple_cat_result<_Tpls...>::__type
2577     {
2578       typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2579       typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2580       typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2581       return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2582     }
2584   // _GLIBCXX_RESOLVE_LIB_DEFECTS
2585   // 2301. Why is tie not constexpr?
2586   /// Return a tuple of lvalue references bound to the arguments
2587   template<typename... _Elements>
2588     constexpr tuple<_Elements&...>
2589     tie(_Elements&... __args) noexcept
2590     { return tuple<_Elements&...>(__args...); }
2592   /// Exchange the values of two tuples
2593   template<typename... _Elements>
2594     _GLIBCXX20_CONSTEXPR
2595     inline
2596 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2597     // Constrained free swap overload, see p0185r1
2598     typename enable_if<__and_<__is_swappable<_Elements>...>::value
2599       >::type
2600 #else
2601     void
2602 #endif
2603     swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
2604     noexcept(noexcept(__x.swap(__y)))
2605     { __x.swap(__y); }
2607 #if __cpp_lib_ranges_zip // >= C++23
2608   template<typename... _Elements>
2609     requires (is_swappable_v<const _Elements> && ...)
2610     constexpr void
2611     swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2612     noexcept(noexcept(__x.swap(__y)))
2613     { __x.swap(__y); }
2614 #endif // C++23
2616 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2617   /// Exchange the values of two const tuples (if const elements can be swapped)
2618   template<typename... _Elements>
2619     _GLIBCXX20_CONSTEXPR
2620     typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2621     swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2622 #endif
2624   // A class (and instance) which can be used in 'tie' when an element
2625   // of a tuple is not required.
2626   // _GLIBCXX14_CONSTEXPR
2627   // 2933. PR for LWG 2773 could be clearer
2628   struct _Swallow_assign
2629   {
2630     template<class _Tp>
2631       _GLIBCXX14_CONSTEXPR const _Swallow_assign&
2632       operator=(const _Tp&) const
2633       { return *this; }
2634   };
2636   // _GLIBCXX_RESOLVE_LIB_DEFECTS
2637   // 2773. Making std::ignore constexpr
2638   /** Used with `std::tie` to ignore an element of a tuple
2639    *
2640    * When using `std::tie` to assign the elements of a tuple to variables,
2641    * unwanted elements can be ignored by using `std::ignore`. For example:
2642    *
2643    * ```
2644    * int x, y;
2645    * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3);
2646    * ```
2647    *
2648    * This assignment will perform `x=1; std::ignore=2; y=3;` which results
2649    * in the second element being ignored.
2650    *
2651    * @since C++11
2652    */
2653   _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{};
2655   /// Partial specialization for tuples
2656   template<typename... _Types, typename _Alloc>
2657     struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2659   // See stl_pair.h...
2660   /** "piecewise construction" using a tuple of arguments for each member.
2661    *
2662    * @param __first Arguments for the first member of the pair.
2663    * @param __second Arguments for the second member of the pair.
2664    *
2665    * The elements of each tuple will be used as the constructor arguments
2666    * for the data members of the pair.
2667   */
2668   template<class _T1, class _T2>
2669     template<typename... _Args1, typename... _Args2>
2670       _GLIBCXX20_CONSTEXPR
2671       inline
2672       pair<_T1, _T2>::
2673       pair(piecewise_construct_t,
2674            tuple<_Args1...> __first, tuple<_Args2...> __second)
2675       : pair(__first, __second,
2676              typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2677              typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2678       { }
2680   template<class _T1, class _T2>
2681     template<typename... _Args1, size_t... _Indexes1,
2682              typename... _Args2, size_t... _Indexes2>
2683       _GLIBCXX20_CONSTEXPR inline
2684       pair<_T1, _T2>::
2685       pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2686            _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2687       : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2688         second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2689       { }
2691 #if defined(__cpp_lib_apply) || defined(__cpp_lib_make_from_tuple) // C++ >= 17
2692   // Unpack a std::tuple into a type trait and use its value.
2693   // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2694   // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2695   // Otherwise the result is false (because we don't know if std::get throws).
2696   template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2697     inline constexpr bool __unpack_std_tuple = false;
2699   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2700     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2701       = _Trait<_Tp, _Up...>::value;
2703   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2704     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2705       = _Trait<_Tp, _Up&...>::value;
2707   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2708     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2709       = _Trait<_Tp, const _Up...>::value;
2711   template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2712     inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2713       = _Trait<_Tp, const _Up&...>::value;
2714 #endif
2716 #ifdef __cpp_lib_apply // C++ >= 17
2717   template <typename _Fn, typename _Tuple, size_t... _Idx>
2718     constexpr decltype(auto)
2719     __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2720     {
2721       return std::__invoke(std::forward<_Fn>(__f),
2722                            std::get<_Idx>(std::forward<_Tuple>(__t))...);
2723     }
2725   template <typename _Fn, typename _Tuple>
2726     constexpr decltype(auto)
2727     apply(_Fn&& __f, _Tuple&& __t)
2728     noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2729     {
2730       using _Indices
2731         = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2732       return std::__apply_impl(std::forward<_Fn>(__f),
2733                                std::forward<_Tuple>(__t),
2734                                _Indices{});
2735     }
2736 #endif
2738 #ifdef __cpp_lib_make_from_tuple // C++ >= 17
2739   template <typename _Tp, typename _Tuple, size_t... _Idx>
2740     constexpr _Tp
2741     __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
2742     { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
2744   template <typename _Tp, typename _Tuple>
2745     constexpr _Tp
2746     make_from_tuple(_Tuple&& __t)
2747     noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
2748     {
2749       constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
2750 #if __has_builtin(__reference_constructs_from_temporary)
2751       if constexpr (__n == 1)
2752         {
2753           using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
2754           static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
2755         }
2756 #endif
2757       return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
2758                                          make_index_sequence<__n>{});
2759     }
2760 #endif
2762 #if __cpp_lib_ranges_zip // >= C++23
2763   template<typename... _TTypes, typename... _UTypes,
2764            template<typename> class _TQual, template<typename> class _UQual>
2765     requires requires { typename tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; }
2766   struct basic_common_reference<tuple<_TTypes...>, tuple<_UTypes...>, _TQual, _UQual>
2767   { using type = tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; };
2769   template<typename... _TTypes, typename... _UTypes>
2770     requires requires { typename tuple<common_type_t<_TTypes, _UTypes>...>; }
2771   struct common_type<tuple<_TTypes...>, tuple<_UTypes...>>
2772   { using type = tuple<common_type_t<_TTypes, _UTypes>...>; };
2773 #endif // C++23
2775   /// @}
2777 #undef __glibcxx_no_dangling_refs
2779 _GLIBCXX_END_NAMESPACE_VERSION
2780 } // namespace std
2782 #endif // C++11
2784 #endif // _GLIBCXX_TUPLE