libstdc++
tuple
Go to the documentation of this file.
1 // <tuple> -*- C++ -*-
2 
3 // Copyright (C) 2007-2023 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.
10 
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.
15 
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.
19 
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/>.
24 
25 /** @file include/tuple
26  * This is a Standard C++ Library header.
27  */
28 
29 #ifndef _GLIBCXX_TUPLE
30 #define _GLIBCXX_TUPLE 1
31 
32 #pragma GCC system_header
33 
34 #if __cplusplus < 201103L
35 # include <bits/c++0x_warning.h>
36 #else
37 
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 # define __cpp_lib_constexpr_tuple 201811L
46 #endif
47 
48 namespace std _GLIBCXX_VISIBILITY(default)
49 {
50 _GLIBCXX_BEGIN_NAMESPACE_VERSION
51 
52  /**
53  * @addtogroup utilities
54  * @{
55  */
56 
57  template<typename... _Elements>
58  class tuple;
59 
60  template<typename _Tp>
61  struct __is_empty_non_tuple : is_empty<_Tp> { };
62 
63  // Using EBO for elements that are tuples causes ambiguous base errors.
64  template<typename _El0, typename... _El>
65  struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { };
66 
67  // Use the Empty Base-class Optimization for empty, non-final types.
68  template<typename _Tp>
69  using __empty_not_final
70  = __conditional_t<__is_final(_Tp), false_type,
71  __is_empty_non_tuple<_Tp>>;
72 
73  template<size_t _Idx, typename _Head,
74  bool = __empty_not_final<_Head>::value>
75  struct _Head_base;
76 
77 #if __has_cpp_attribute(__no_unique_address__)
78  template<size_t _Idx, typename _Head>
79  struct _Head_base<_Idx, _Head, true>
80  {
81  constexpr _Head_base()
82  : _M_head_impl() { }
83 
84  constexpr _Head_base(const _Head& __h)
85  : _M_head_impl(__h) { }
86 
87  constexpr _Head_base(const _Head_base&) = default;
88  constexpr _Head_base(_Head_base&&) = default;
89 
90  template<typename _UHead>
91  constexpr _Head_base(_UHead&& __h)
92  : _M_head_impl(std::forward<_UHead>(__h)) { }
93 
94  _GLIBCXX20_CONSTEXPR
95  _Head_base(allocator_arg_t, __uses_alloc0)
96  : _M_head_impl() { }
97 
98  template<typename _Alloc>
99  _GLIBCXX20_CONSTEXPR
100  _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
101  : _M_head_impl(allocator_arg, *__a._M_a) { }
102 
103  template<typename _Alloc>
104  _GLIBCXX20_CONSTEXPR
105  _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
106  : _M_head_impl(*__a._M_a) { }
107 
108  template<typename _UHead>
109  _GLIBCXX20_CONSTEXPR
110  _Head_base(__uses_alloc0, _UHead&& __uhead)
111  : _M_head_impl(std::forward<_UHead>(__uhead)) { }
112 
113  template<typename _Alloc, typename _UHead>
114  _GLIBCXX20_CONSTEXPR
115  _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
116  : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
117  { }
118 
119  template<typename _Alloc, typename _UHead>
120  _GLIBCXX20_CONSTEXPR
121  _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
122  : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
123 
124  static constexpr _Head&
125  _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
126 
127  static constexpr const _Head&
128  _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
129 
130  [[__no_unique_address__]] _Head _M_head_impl;
131  };
132 #else
133  template<size_t _Idx, typename _Head>
134  struct _Head_base<_Idx, _Head, true>
135  : public _Head
136  {
137  constexpr _Head_base()
138  : _Head() { }
139 
140  constexpr _Head_base(const _Head& __h)
141  : _Head(__h) { }
142 
143  constexpr _Head_base(const _Head_base&) = default;
144  constexpr _Head_base(_Head_base&&) = default;
145 
146  template<typename _UHead>
147  constexpr _Head_base(_UHead&& __h)
148  : _Head(std::forward<_UHead>(__h)) { }
149 
150  _GLIBCXX20_CONSTEXPR
151  _Head_base(allocator_arg_t, __uses_alloc0)
152  : _Head() { }
153 
154  template<typename _Alloc>
155  _GLIBCXX20_CONSTEXPR
156  _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
157  : _Head(allocator_arg, *__a._M_a) { }
158 
159  template<typename _Alloc>
160  _GLIBCXX20_CONSTEXPR
161  _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
162  : _Head(*__a._M_a) { }
163 
164  template<typename _UHead>
165  _GLIBCXX20_CONSTEXPR
166  _Head_base(__uses_alloc0, _UHead&& __uhead)
167  : _Head(std::forward<_UHead>(__uhead)) { }
168 
169  template<typename _Alloc, typename _UHead>
170  _GLIBCXX20_CONSTEXPR
171  _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
172  : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
173 
174  template<typename _Alloc, typename _UHead>
175  _GLIBCXX20_CONSTEXPR
176  _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
177  : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
178 
179  static constexpr _Head&
180  _M_head(_Head_base& __b) noexcept { return __b; }
181 
182  static constexpr const _Head&
183  _M_head(const _Head_base& __b) noexcept { return __b; }
184  };
185 #endif
186 
187  template<size_t _Idx, typename _Head>
188  struct _Head_base<_Idx, _Head, false>
189  {
190  constexpr _Head_base()
191  : _M_head_impl() { }
192 
193  constexpr _Head_base(const _Head& __h)
194  : _M_head_impl(__h) { }
195 
196  constexpr _Head_base(const _Head_base&) = default;
197  constexpr _Head_base(_Head_base&&) = default;
198 
199  template<typename _UHead>
200  constexpr _Head_base(_UHead&& __h)
201  : _M_head_impl(std::forward<_UHead>(__h)) { }
202 
203  _GLIBCXX20_CONSTEXPR
204  _Head_base(allocator_arg_t, __uses_alloc0)
205  : _M_head_impl() { }
206 
207  template<typename _Alloc>
208  _GLIBCXX20_CONSTEXPR
209  _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
210  : _M_head_impl(allocator_arg, *__a._M_a) { }
211 
212  template<typename _Alloc>
213  _GLIBCXX20_CONSTEXPR
214  _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
215  : _M_head_impl(*__a._M_a) { }
216 
217  template<typename _UHead>
218  _GLIBCXX20_CONSTEXPR
219  _Head_base(__uses_alloc0, _UHead&& __uhead)
220  : _M_head_impl(std::forward<_UHead>(__uhead)) { }
221 
222  template<typename _Alloc, typename _UHead>
223  _GLIBCXX20_CONSTEXPR
224  _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
225  : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
226  { }
227 
228  template<typename _Alloc, typename _UHead>
229  _GLIBCXX20_CONSTEXPR
230  _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
231  : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
232 
233  static constexpr _Head&
234  _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
235 
236  static constexpr const _Head&
237  _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
238 
239  _Head _M_head_impl;
240  };
241 
242  /**
243  * Contains the actual implementation of the @c tuple template, stored
244  * as a recursive inheritance hierarchy from the first element (most
245  * derived class) to the last (least derived class). The @c Idx
246  * parameter gives the 0-based index of the element stored at this
247  * point in the hierarchy; we use it to implement a constant-time
248  * get() operation.
249  */
250  template<size_t _Idx, typename... _Elements>
251  struct _Tuple_impl;
252 
253  /**
254  * Recursive tuple implementation. Here we store the @c Head element
255  * and derive from a @c Tuple_impl containing the remaining elements
256  * (which contains the @c Tail).
257  */
258  template<size_t _Idx, typename _Head, typename... _Tail>
259  struct _Tuple_impl<_Idx, _Head, _Tail...>
260  : public _Tuple_impl<_Idx + 1, _Tail...>,
261  private _Head_base<_Idx, _Head>
262  {
263  template<size_t, typename...> friend struct _Tuple_impl;
264 
265  typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
266  typedef _Head_base<_Idx, _Head> _Base;
267 
268  static constexpr _Head&
269  _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
270 
271  static constexpr const _Head&
272  _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
273 
274  static constexpr _Inherited&
275  _M_tail(_Tuple_impl& __t) noexcept { return __t; }
276 
277  static constexpr const _Inherited&
278  _M_tail(const _Tuple_impl& __t) noexcept { return __t; }
279 
280  constexpr _Tuple_impl()
281  : _Inherited(), _Base() { }
282 
283  explicit constexpr
284  _Tuple_impl(const _Head& __head, const _Tail&... __tail)
285  : _Inherited(__tail...), _Base(__head)
286  { }
287 
288  template<typename _UHead, typename... _UTail,
289  typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
290  explicit constexpr
291  _Tuple_impl(_UHead&& __head, _UTail&&... __tail)
292  : _Inherited(std::forward<_UTail>(__tail)...),
293  _Base(std::forward<_UHead>(__head))
294  { }
295 
296  constexpr _Tuple_impl(const _Tuple_impl&) = default;
297 
298  // _GLIBCXX_RESOLVE_LIB_DEFECTS
299  // 2729. Missing SFINAE on std::pair::operator=
300  _Tuple_impl& operator=(const _Tuple_impl&) = delete;
301 
302  _Tuple_impl(_Tuple_impl&&) = default;
303 
304  template<typename... _UElements>
305  constexpr
306  _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
307  : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
308  _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
309  { }
310 
311  template<typename _UHead, typename... _UTails>
312  constexpr
313  _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
314  : _Inherited(std::move
315  (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
316  _Base(std::forward<_UHead>
317  (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
318  { }
319 
320 #if __cplusplus > 202002L
321  template<typename... _UElements>
322  constexpr
323  _Tuple_impl(_Tuple_impl<_Idx, _UElements...>& __in)
324  : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
325  _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
326  { }
327 
328  template<typename _UHead, typename... _UTails>
329  constexpr
330  _Tuple_impl(const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
331  : _Inherited(std::move
332  (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
333  _Base(std::forward<const _UHead>
334  (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
335  { }
336 #endif // C++23
337 
338  template<typename _Alloc>
339  _GLIBCXX20_CONSTEXPR
340  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
341  : _Inherited(__tag, __a),
342  _Base(__tag, __use_alloc<_Head>(__a))
343  { }
344 
345  template<typename _Alloc>
346  _GLIBCXX20_CONSTEXPR
347  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
348  const _Head& __head, const _Tail&... __tail)
349  : _Inherited(__tag, __a, __tail...),
350  _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head)
351  { }
352 
353  template<typename _Alloc, typename _UHead, typename... _UTail,
354  typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
355  _GLIBCXX20_CONSTEXPR
356  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
357  _UHead&& __head, _UTail&&... __tail)
358  : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
359  _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
360  std::forward<_UHead>(__head))
361  { }
362 
363  template<typename _Alloc>
364  _GLIBCXX20_CONSTEXPR
365  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
366  const _Tuple_impl& __in)
367  : _Inherited(__tag, __a, _M_tail(__in)),
368  _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in))
369  { }
370 
371  template<typename _Alloc>
372  _GLIBCXX20_CONSTEXPR
373  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
374  _Tuple_impl&& __in)
375  : _Inherited(__tag, __a, std::move(_M_tail(__in))),
376  _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
377  std::forward<_Head>(_M_head(__in)))
378  { }
379 
380  template<typename _Alloc, typename _UHead, typename... _UTails>
381  _GLIBCXX20_CONSTEXPR
382  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
383  const _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
384  : _Inherited(__tag, __a,
385  _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
386  _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
387  _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
388  { }
389 
390  template<typename _Alloc, typename _UHead, typename... _UTails>
391  _GLIBCXX20_CONSTEXPR
392  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
393  _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
394  : _Inherited(__tag, __a, std::move
395  (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
396  _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
397  std::forward<_UHead>
398  (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
399  { }
400 
401 #if __cplusplus > 202002L
402  template<typename _Alloc, typename _UHead, typename... _UTails>
403  constexpr
404  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
405  _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
406  : _Inherited(__tag, __a,
407  _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
408  _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
409  _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
410  { }
411 
412  template<typename _Alloc, typename _UHead, typename... _UTails>
413  constexpr
414  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
415  const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
416  : _Inherited(__tag, __a, std::move
417  (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
418  _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
419  std::forward<const _UHead>
420  (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
421  { }
422 #endif // C++23
423 
424  template<typename... _UElements>
425  _GLIBCXX20_CONSTEXPR
426  void
427  _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in)
428  {
429  _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
430  _M_tail(*this)._M_assign(
431  _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
432  }
433 
434  template<typename _UHead, typename... _UTails>
435  _GLIBCXX20_CONSTEXPR
436  void
437  _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
438  {
439  _M_head(*this) = std::forward<_UHead>
440  (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
441  _M_tail(*this)._M_assign(
442  std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
443  }
444 
445 #if __cplusplus > 202002L
446  template<typename... _UElements>
447  constexpr void
448  _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) const
449  {
450  _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
451  _M_tail(*this)._M_assign(
452  _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
453  }
454 
455  template<typename _UHead, typename... _UTails>
456  constexpr void
457  _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) const
458  {
459  _M_head(*this) = std::forward<_UHead>
460  (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
461  _M_tail(*this)._M_assign(
462  std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
463  }
464 #endif // C++23
465 
466  protected:
467  _GLIBCXX20_CONSTEXPR
468  void
469  _M_swap(_Tuple_impl& __in)
470  {
471  using std::swap;
472  swap(_M_head(*this), _M_head(__in));
473  _Inherited::_M_swap(_M_tail(__in));
474  }
475 
476 #if __cplusplus > 202002L
477  constexpr void
478  _M_swap(const _Tuple_impl& __in) const
479  {
480  using std::swap;
481  swap(_M_head(*this), _M_head(__in));
482  _Inherited::_M_swap(_M_tail(__in));
483  }
484 #endif // C++23
485  };
486 
487  // Basis case of inheritance recursion.
488  template<size_t _Idx, typename _Head>
489  struct _Tuple_impl<_Idx, _Head>
490  : private _Head_base<_Idx, _Head>
491  {
492  template<size_t, typename...> friend struct _Tuple_impl;
493 
494  typedef _Head_base<_Idx, _Head> _Base;
495 
496  static constexpr _Head&
497  _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
498 
499  static constexpr const _Head&
500  _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
501 
502  constexpr
503  _Tuple_impl()
504  : _Base() { }
505 
506  explicit constexpr
507  _Tuple_impl(const _Head& __head)
508  : _Base(__head)
509  { }
510 
511  template<typename _UHead>
512  explicit constexpr
513  _Tuple_impl(_UHead&& __head)
514  : _Base(std::forward<_UHead>(__head))
515  { }
516 
517  constexpr _Tuple_impl(const _Tuple_impl&) = default;
518 
519  // _GLIBCXX_RESOLVE_LIB_DEFECTS
520  // 2729. Missing SFINAE on std::pair::operator=
521  _Tuple_impl& operator=(const _Tuple_impl&) = delete;
522 
523 #if _GLIBCXX_INLINE_VERSION
524  _Tuple_impl(_Tuple_impl&&) = default;
525 #else
526  constexpr
527  _Tuple_impl(_Tuple_impl&& __in)
528  noexcept(is_nothrow_move_constructible<_Head>::value)
529  : _Base(static_cast<_Base&&>(__in))
530  { }
531 #endif
532 
533  template<typename _UHead>
534  constexpr
535  _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in)
536  : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
537  { }
538 
539  template<typename _UHead>
540  constexpr
541  _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in)
542  : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
543  { }
544 
545 #if __cplusplus > 202002L
546  template<typename _UHead>
547  constexpr
548  _Tuple_impl(_Tuple_impl<_Idx, _UHead>& __in)
549  : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
550  { }
551 
552  template<typename _UHead>
553  constexpr
554  _Tuple_impl(const _Tuple_impl<_Idx, _UHead>&& __in)
555  : _Base(std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
556  { }
557 #endif // C++23
558 
559  template<typename _Alloc>
560  _GLIBCXX20_CONSTEXPR
561  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
562  : _Base(__tag, __use_alloc<_Head>(__a))
563  { }
564 
565  template<typename _Alloc>
566  _GLIBCXX20_CONSTEXPR
567  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
568  const _Head& __head)
569  : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), __head)
570  { }
571 
572  template<typename _Alloc, typename _UHead>
573  _GLIBCXX20_CONSTEXPR
574  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
575  _UHead&& __head)
576  : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
577  std::forward<_UHead>(__head))
578  { }
579 
580  template<typename _Alloc>
581  _GLIBCXX20_CONSTEXPR
582  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
583  const _Tuple_impl& __in)
584  : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), _M_head(__in))
585  { }
586 
587  template<typename _Alloc>
588  _GLIBCXX20_CONSTEXPR
589  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
590  _Tuple_impl&& __in)
591  : _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
592  std::forward<_Head>(_M_head(__in)))
593  { }
594 
595  template<typename _Alloc, typename _UHead>
596  _GLIBCXX20_CONSTEXPR
597  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
598  const _Tuple_impl<_Idx, _UHead>& __in)
599  : _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
600  _Tuple_impl<_Idx, _UHead>::_M_head(__in))
601  { }
602 
603  template<typename _Alloc, typename _UHead>
604  _GLIBCXX20_CONSTEXPR
605  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
606  _Tuple_impl<_Idx, _UHead>&& __in)
607  : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
608  std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
609  { }
610 
611 #if __cplusplus > 202002L
612  template<typename _Alloc, typename _UHead>
613  constexpr
614  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
615  _Tuple_impl<_Idx, _UHead>& __in)
616  : _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
617  _Tuple_impl<_Idx, _UHead>::_M_head(__in))
618  { }
619 
620  template<typename _Alloc, typename _UHead>
621  constexpr
622  _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
623  const _Tuple_impl<_Idx, _UHead>&& __in)
624  : _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
625  std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
626  { }
627 #endif // C++23
628 
629  template<typename _UHead>
630  _GLIBCXX20_CONSTEXPR
631  void
632  _M_assign(const _Tuple_impl<_Idx, _UHead>& __in)
633  {
634  _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
635  }
636 
637  template<typename _UHead>
638  _GLIBCXX20_CONSTEXPR
639  void
640  _M_assign(_Tuple_impl<_Idx, _UHead>&& __in)
641  {
642  _M_head(*this)
643  = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
644  }
645 
646 #if __cplusplus > 202002L
647  template<typename _UHead>
648  constexpr void
649  _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) const
650  {
651  _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
652  }
653 
654  template<typename _UHead>
655  constexpr void
656  _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) const
657  {
658  _M_head(*this)
659  = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
660  }
661 #endif // C++23
662 
663  protected:
664  _GLIBCXX20_CONSTEXPR
665  void
666  _M_swap(_Tuple_impl& __in)
667  {
668  using std::swap;
669  swap(_M_head(*this), _M_head(__in));
670  }
671 
672 #if __cplusplus > 202002L
673  constexpr void
674  _M_swap(const _Tuple_impl& __in) const
675  {
676  using std::swap;
677  swap(_M_head(*this), _M_head(__in));
678  }
679 #endif // C++23
680  };
681 
682  // Concept utility functions, reused in conditionally-explicit
683  // constructors.
684  template<bool, typename... _Types>
685  struct _TupleConstraints
686  {
687  template<typename... _UTypes>
688  using __constructible = __and_<is_constructible<_Types, _UTypes>...>;
689 
690  template<typename... _UTypes>
691  using __convertible = __and_<is_convertible<_UTypes, _Types>...>;
692 
693  // Constraint for a non-explicit constructor.
694  // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
695  // and every Ui is implicitly convertible to Ti.
696  template<typename... _UTypes>
697  static constexpr bool __is_implicitly_constructible()
698  {
699  return __and_<__constructible<_UTypes...>,
700  __convertible<_UTypes...>
701  >::value;
702  }
703 
704  // Constraint for a non-explicit constructor.
705  // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
706  // but not every Ui is implicitly convertible to Ti.
707  template<typename... _UTypes>
708  static constexpr bool __is_explicitly_constructible()
709  {
710  return __and_<__constructible<_UTypes...>,
711  __not_<__convertible<_UTypes...>>
712  >::value;
713  }
714 
715  static constexpr bool __is_implicitly_default_constructible()
716  {
717  return __and_<std::__is_implicitly_default_constructible<_Types>...
718  >::value;
719  }
720 
721  static constexpr bool __is_explicitly_default_constructible()
722  {
723  return __and_<is_default_constructible<_Types>...,
724  __not_<__and_<
725  std::__is_implicitly_default_constructible<_Types>...>
726  >>::value;
727  }
728  };
729 
730  // Partial specialization used when a required precondition isn't met,
731  // e.g. when sizeof...(_Types) != sizeof...(_UTypes).
732  template<typename... _Types>
733  struct _TupleConstraints<false, _Types...>
734  {
735  template<typename... _UTypes>
736  static constexpr bool __is_implicitly_constructible()
737  { return false; }
738 
739  template<typename... _UTypes>
740  static constexpr bool __is_explicitly_constructible()
741  { return false; }
742  };
743 
744  /// Primary class template, tuple
745  template<typename... _Elements>
746  class tuple : public _Tuple_impl<0, _Elements...>
747  {
748  typedef _Tuple_impl<0, _Elements...> _Inherited;
749 
750  template<bool _Cond>
751  using _TCC = _TupleConstraints<_Cond, _Elements...>;
752 
753  // Constraint for non-explicit default constructor
754  template<bool _Dummy>
755  using _ImplicitDefaultCtor = __enable_if_t<
756  _TCC<_Dummy>::__is_implicitly_default_constructible(),
757  bool>;
758 
759  // Constraint for explicit default constructor
760  template<bool _Dummy>
761  using _ExplicitDefaultCtor = __enable_if_t<
762  _TCC<_Dummy>::__is_explicitly_default_constructible(),
763  bool>;
764 
765  // Constraint for non-explicit constructors
766  template<bool _Cond, typename... _Args>
767  using _ImplicitCtor = __enable_if_t<
768  _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
769  bool>;
770 
771  // Constraint for non-explicit constructors
772  template<bool _Cond, typename... _Args>
773  using _ExplicitCtor = __enable_if_t<
774  _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
775  bool>;
776 
777  template<typename... _UElements>
778  static constexpr
779  __enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
780  __assignable()
781  { return __and_<is_assignable<_Elements&, _UElements>...>::value; }
782 
783  // Condition for noexcept-specifier of an assignment operator.
784  template<typename... _UElements>
785  static constexpr bool __nothrow_assignable()
786  {
787  return
788  __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
789  }
790 
791  // Condition for noexcept-specifier of a constructor.
792  template<typename... _UElements>
793  static constexpr bool __nothrow_constructible()
794  {
795  return
796  __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
797  }
798 
799  // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1.
800  template<typename _Up>
801  static constexpr bool __valid_args()
802  {
803  return sizeof...(_Elements) == 1
804  && !is_same<tuple, __remove_cvref_t<_Up>>::value;
805  }
806 
807  // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1.
808  template<typename, typename, typename... _Tail>
809  static constexpr bool __valid_args()
810  { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); }
811 
812  /* Constraint for constructors with a tuple<UTypes...> parameter ensures
813  * that the constructor is only viable when it would not interfere with
814  * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&).
815  * Such constructors are only viable if:
816  * either sizeof...(Types) != 1,
817  * or (when Types... expands to T and UTypes... expands to U)
818  * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>,
819  * and is_same_v<T, U> are all false.
820  */
821  template<typename _Tuple, typename = tuple,
822  typename = __remove_cvref_t<_Tuple>>
823  struct _UseOtherCtor
824  : false_type
825  { };
826  // If TUPLE is convertible to the single element in *this,
827  // then TUPLE should match tuple(UTypes&&...) instead.
828  template<typename _Tuple, typename _Tp, typename _Up>
829  struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>>
830  : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>::type
831  { };
832  // If TUPLE and *this each have a single element of the same type,
833  // then TUPLE should match a copy/move constructor instead.
834  template<typename _Tuple, typename _Tp>
835  struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>>
836  : true_type
837  { };
838 
839  // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
840  // and the single element in Types can be initialized from TUPLE,
841  // or is the same type as tuple_element_t<0, TUPLE>.
842  template<typename _Tuple>
843  static constexpr bool __use_other_ctor()
844  { return _UseOtherCtor<_Tuple>::value; }
845 
846 #if __cplusplus > 202002L
847  template<typename... _Args>
848  static constexpr bool __constructible
849  = _TCC<true>::template __constructible<_Args...>::value;
850 
851  template<typename... _Args>
852  static constexpr bool __convertible
853  = _TCC<true>::template __convertible<_Args...>::value;
854 #endif // C++23
855 
856  public:
857  template<typename _Dummy = void,
858  _ImplicitDefaultCtor<is_void<_Dummy>::value> = true>
859  constexpr
860  tuple()
861  noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
862  : _Inherited() { }
863 
864  template<typename _Dummy = void,
865  _ExplicitDefaultCtor<is_void<_Dummy>::value> = false>
866  explicit constexpr
867  tuple()
868  noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
869  : _Inherited() { }
870 
871  template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
872  _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
873  constexpr
874  tuple(const _Elements&... __elements)
875  noexcept(__nothrow_constructible<const _Elements&...>())
876  : _Inherited(__elements...) { }
877 
878  template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
879  _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
880  explicit constexpr
881  tuple(const _Elements&... __elements)
882  noexcept(__nothrow_constructible<const _Elements&...>())
883  : _Inherited(__elements...) { }
884 
885  template<typename... _UElements,
886  bool _Valid = __valid_args<_UElements...>(),
887  _ImplicitCtor<_Valid, _UElements...> = true>
888  constexpr
889  tuple(_UElements&&... __elements)
890  noexcept(__nothrow_constructible<_UElements...>())
891  : _Inherited(std::forward<_UElements>(__elements)...) { }
892 
893  template<typename... _UElements,
894  bool _Valid = __valid_args<_UElements...>(),
895  _ExplicitCtor<_Valid, _UElements...> = false>
896  explicit constexpr
897  tuple(_UElements&&... __elements)
898  noexcept(__nothrow_constructible<_UElements...>())
899  : _Inherited(std::forward<_UElements>(__elements)...) { }
900 
901  constexpr tuple(const tuple&) = default;
902 
903  constexpr tuple(tuple&&) = default;
904 
905  template<typename... _UElements,
906  bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
907  && !__use_other_ctor<const tuple<_UElements...>&>(),
908  _ImplicitCtor<_Valid, const _UElements&...> = true>
909  constexpr
910  tuple(const tuple<_UElements...>& __in)
911  noexcept(__nothrow_constructible<const _UElements&...>())
912  : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
913  { }
914 
915  template<typename... _UElements,
916  bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
917  && !__use_other_ctor<const tuple<_UElements...>&>(),
918  _ExplicitCtor<_Valid, const _UElements&...> = false>
919  explicit constexpr
920  tuple(const tuple<_UElements...>& __in)
921  noexcept(__nothrow_constructible<const _UElements&...>())
922  : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
923  { }
924 
925  template<typename... _UElements,
926  bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
927  && !__use_other_ctor<tuple<_UElements...>&&>(),
928  _ImplicitCtor<_Valid, _UElements...> = true>
929  constexpr
930  tuple(tuple<_UElements...>&& __in)
931  noexcept(__nothrow_constructible<_UElements...>())
932  : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
933 
934  template<typename... _UElements,
935  bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
936  && !__use_other_ctor<tuple<_UElements...>&&>(),
937  _ExplicitCtor<_Valid, _UElements...> = false>
938  explicit constexpr
939  tuple(tuple<_UElements...>&& __in)
940  noexcept(__nothrow_constructible<_UElements...>())
941  : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
942 
943 #if __cplusplus > 202002L
944  template<typename... _UElements>
945  requires (sizeof...(_Elements) == sizeof...(_UElements))
946  && (!__use_other_ctor<tuple<_UElements...>&>())
947  && __constructible<_UElements&...>
948  explicit(!__convertible<_UElements&...>)
949  constexpr
950  tuple(tuple<_UElements...>& __in)
951  noexcept(__nothrow_constructible<_UElements&...>())
952  : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&>(__in))
953  { }
954 
955  template<typename... _UElements>
956  requires (sizeof...(_Elements) == sizeof...(_UElements))
957  && (!__use_other_ctor<const tuple<_UElements...>&&>())
958  && __constructible<const _UElements...>
959  explicit(!__convertible<const _UElements...>)
960  constexpr
961  tuple(const tuple<_UElements...>&& __in)
962  noexcept(__nothrow_constructible<const _UElements...>())
963  : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&&>(__in)) { }
964 #endif // C++23
965 
966  // Allocator-extended constructors.
967 
968  template<typename _Alloc,
969  _ImplicitDefaultCtor<is_object<_Alloc>::value> = true>
970  _GLIBCXX20_CONSTEXPR
971  tuple(allocator_arg_t __tag, const _Alloc& __a)
972  : _Inherited(__tag, __a) { }
973 
974  template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
975  _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
976  _GLIBCXX20_CONSTEXPR
977  tuple(allocator_arg_t __tag, const _Alloc& __a,
978  const _Elements&... __elements)
979  : _Inherited(__tag, __a, __elements...) { }
980 
981  template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
982  _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
983  _GLIBCXX20_CONSTEXPR
984  explicit
985  tuple(allocator_arg_t __tag, const _Alloc& __a,
986  const _Elements&... __elements)
987  : _Inherited(__tag, __a, __elements...) { }
988 
989  template<typename _Alloc, typename... _UElements,
990  bool _Valid = __valid_args<_UElements...>(),
991  _ImplicitCtor<_Valid, _UElements...> = true>
992  _GLIBCXX20_CONSTEXPR
993  tuple(allocator_arg_t __tag, const _Alloc& __a,
994  _UElements&&... __elements)
995  : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
996  { }
997 
998  template<typename _Alloc, typename... _UElements,
999  bool _Valid = __valid_args<_UElements...>(),
1000  _ExplicitCtor<_Valid, _UElements...> = false>
1001  _GLIBCXX20_CONSTEXPR
1002  explicit
1003  tuple(allocator_arg_t __tag, const _Alloc& __a,
1004  _UElements&&... __elements)
1005  : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1006  { }
1007 
1008  template<typename _Alloc>
1009  _GLIBCXX20_CONSTEXPR
1010  tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1011  : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1012 
1013  template<typename _Alloc>
1014  _GLIBCXX20_CONSTEXPR
1015  tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1016  : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1017 
1018  template<typename _Alloc, typename... _UElements,
1019  bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1020  && !__use_other_ctor<const tuple<_UElements...>&>(),
1021  _ImplicitCtor<_Valid, const _UElements&...> = true>
1022  _GLIBCXX20_CONSTEXPR
1023  tuple(allocator_arg_t __tag, const _Alloc& __a,
1024  const tuple<_UElements...>& __in)
1025  : _Inherited(__tag, __a,
1026  static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1027  { }
1028 
1029  template<typename _Alloc, typename... _UElements,
1030  bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1031  && !__use_other_ctor<const tuple<_UElements...>&>(),
1032  _ExplicitCtor<_Valid, const _UElements&...> = false>
1033  _GLIBCXX20_CONSTEXPR
1034  explicit
1035  tuple(allocator_arg_t __tag, const _Alloc& __a,
1036  const tuple<_UElements...>& __in)
1037  : _Inherited(__tag, __a,
1038  static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1039  { }
1040 
1041  template<typename _Alloc, typename... _UElements,
1042  bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1043  && !__use_other_ctor<tuple<_UElements...>&&>(),
1044  _ImplicitCtor<_Valid, _UElements...> = true>
1045  _GLIBCXX20_CONSTEXPR
1046  tuple(allocator_arg_t __tag, const _Alloc& __a,
1047  tuple<_UElements...>&& __in)
1048  : _Inherited(__tag, __a,
1049  static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1050  { }
1051 
1052  template<typename _Alloc, typename... _UElements,
1053  bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1054  && !__use_other_ctor<tuple<_UElements...>&&>(),
1055  _ExplicitCtor<_Valid, _UElements...> = false>
1056  _GLIBCXX20_CONSTEXPR
1057  explicit
1058  tuple(allocator_arg_t __tag, const _Alloc& __a,
1059  tuple<_UElements...>&& __in)
1060  : _Inherited(__tag, __a,
1061  static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1062  { }
1063 
1064 #if __cplusplus > 202002L
1065  template<typename _Alloc, typename... _UElements>
1066  requires (sizeof...(_Elements) == sizeof...(_UElements))
1067  && (!__use_other_ctor<tuple<_UElements...>&>())
1068  && __constructible<_UElements&...>
1069  explicit(!__convertible<_UElements&...>)
1070  constexpr
1071  tuple(allocator_arg_t __tag, const _Alloc& __a,
1072  tuple<_UElements...>& __in)
1073  : _Inherited(__tag, __a,
1074  static_cast<_Tuple_impl<0, _UElements...>&>(__in))
1075  { }
1076 
1077  template<typename _Alloc, typename... _UElements>
1078  requires (sizeof...(_Elements) == sizeof...(_UElements))
1079  && (!__use_other_ctor<const tuple<_UElements...>>())
1080  && __constructible<const _UElements...>
1081  explicit(!__convertible<const _UElements...>)
1082  constexpr
1083  tuple(allocator_arg_t __tag, const _Alloc& __a,
1084  const tuple<_UElements...>&& __in)
1085  : _Inherited(__tag, __a,
1086  static_cast<const _Tuple_impl<0, _UElements...>&&>(__in))
1087  { }
1088 #endif // C++23
1089 
1090  // tuple assignment
1091 
1092  _GLIBCXX20_CONSTEXPR
1093  tuple&
1094  operator=(__conditional_t<__assignable<const _Elements&...>(),
1095  const tuple&,
1096  const __nonesuch&> __in)
1097  noexcept(__nothrow_assignable<const _Elements&...>())
1098  {
1099  this->_M_assign(__in);
1100  return *this;
1101  }
1102 
1103  _GLIBCXX20_CONSTEXPR
1104  tuple&
1105  operator=(__conditional_t<__assignable<_Elements...>(),
1106  tuple&&,
1107  __nonesuch&&> __in)
1108  noexcept(__nothrow_assignable<_Elements...>())
1109  {
1110  this->_M_assign(std::move(__in));
1111  return *this;
1112  }
1113 
1114  template<typename... _UElements>
1115  _GLIBCXX20_CONSTEXPR
1116  __enable_if_t<__assignable<const _UElements&...>(), tuple&>
1117  operator=(const tuple<_UElements...>& __in)
1118  noexcept(__nothrow_assignable<const _UElements&...>())
1119  {
1120  this->_M_assign(__in);
1121  return *this;
1122  }
1123 
1124  template<typename... _UElements>
1125  _GLIBCXX20_CONSTEXPR
1126  __enable_if_t<__assignable<_UElements...>(), tuple&>
1127  operator=(tuple<_UElements...>&& __in)
1128  noexcept(__nothrow_assignable<_UElements...>())
1129  {
1130  this->_M_assign(std::move(__in));
1131  return *this;
1132  }
1133 
1134 #if __cplusplus > 202002L
1135  constexpr const tuple&
1136  operator=(const tuple& __in) const
1137  requires (is_copy_assignable_v<const _Elements> && ...)
1138  {
1139  this->_M_assign(__in);
1140  return *this;
1141  }
1142 
1143  constexpr const tuple&
1144  operator=(tuple&& __in) const
1145  requires (is_assignable_v<const _Elements&, _Elements> && ...)
1146  {
1147  this->_M_assign(std::move(__in));
1148  return *this;
1149  }
1150 
1151  template<typename... _UElements>
1152  constexpr const tuple&
1153  operator=(const tuple<_UElements...>& __in) const
1154  requires (sizeof...(_Elements) == sizeof...(_UElements))
1155  && (is_assignable_v<const _Elements&, const _UElements&> && ...)
1156  {
1157  this->_M_assign(__in);
1158  return *this;
1159  }
1160 
1161  template<typename... _UElements>
1162  constexpr const tuple&
1163  operator=(tuple<_UElements...>&& __in) const
1164  requires (sizeof...(_Elements) == sizeof...(_UElements))
1165  && (is_assignable_v<const _Elements&, _UElements> && ...)
1166  {
1167  this->_M_assign(std::move(__in));
1168  return *this;
1169  }
1170 #endif // C++23
1171 
1172  // tuple swap
1173  _GLIBCXX20_CONSTEXPR
1174  void
1175  swap(tuple& __in)
1176  noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
1177  { _Inherited::_M_swap(__in); }
1178 
1179 #if __cplusplus > 202002L
1180  // As an extension, we constrain the const swap member function in order
1181  // to continue accepting explicit instantiation of tuples whose elements
1182  // are not all const swappable. Without this constraint, such an
1183  // explicit instantiation would also instantiate the ill-formed body of
1184  // this function and yield a hard error. This constraint shouldn't
1185  // affect the behavior of valid programs.
1186  constexpr void
1187  swap(const tuple& __in) const
1188  noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
1189  requires (is_swappable_v<const _Elements> && ...)
1190  { _Inherited::_M_swap(__in); }
1191 #endif // C++23
1192  };
1193 
1194 #if __cpp_deduction_guides >= 201606
1195  template<typename... _UTypes>
1196  tuple(_UTypes...) -> tuple<_UTypes...>;
1197  template<typename _T1, typename _T2>
1198  tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
1199  template<typename _Alloc, typename... _UTypes>
1200  tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
1201  template<typename _Alloc, typename _T1, typename _T2>
1202  tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
1203  template<typename _Alloc, typename... _UTypes>
1204  tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
1205 #endif
1206 
1207  // Explicit specialization, zero-element tuple.
1208  template<>
1209  class tuple<>
1210  {
1211  public:
1212  _GLIBCXX20_CONSTEXPR
1213  void swap(tuple&) noexcept { /* no-op */ }
1214 #if __cplusplus > 202002L
1215  constexpr void swap(const tuple&) const noexcept { /* no-op */ }
1216 #endif
1217  // We need the default since we're going to define no-op
1218  // allocator constructors.
1219  tuple() = default;
1220  // No-op allocator constructors.
1221  template<typename _Alloc>
1222  _GLIBCXX20_CONSTEXPR
1223  tuple(allocator_arg_t, const _Alloc&) noexcept { }
1224  template<typename _Alloc>
1225  _GLIBCXX20_CONSTEXPR
1226  tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
1227  };
1228 
1229  /// Partial specialization, 2-element tuple.
1230  /// Includes construction and assignment from a pair.
1231  template<typename _T1, typename _T2>
1232  class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
1233  {
1234  typedef _Tuple_impl<0, _T1, _T2> _Inherited;
1235 
1236  // Constraint for non-explicit default constructor
1237  template<bool _Dummy, typename _U1, typename _U2>
1238  using _ImplicitDefaultCtor = __enable_if_t<
1239  _TupleConstraints<_Dummy, _U1, _U2>::
1240  __is_implicitly_default_constructible(),
1241  bool>;
1242 
1243  // Constraint for explicit default constructor
1244  template<bool _Dummy, typename _U1, typename _U2>
1245  using _ExplicitDefaultCtor = __enable_if_t<
1246  _TupleConstraints<_Dummy, _U1, _U2>::
1247  __is_explicitly_default_constructible(),
1248  bool>;
1249 
1250  template<bool _Dummy>
1251  using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
1252 
1253  // Constraint for non-explicit constructors
1254  template<bool _Cond, typename _U1, typename _U2>
1255  using _ImplicitCtor = __enable_if_t<
1256  _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
1257  bool>;
1258 
1259  // Constraint for non-explicit constructors
1260  template<bool _Cond, typename _U1, typename _U2>
1261  using _ExplicitCtor = __enable_if_t<
1262  _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
1263  bool>;
1264 
1265  template<typename _U1, typename _U2>
1266  static constexpr bool __assignable()
1267  {
1268  return __and_<is_assignable<_T1&, _U1>,
1269  is_assignable<_T2&, _U2>>::value;
1270  }
1271 
1272  template<typename _U1, typename _U2>
1273  static constexpr bool __nothrow_assignable()
1274  {
1275  return __and_<is_nothrow_assignable<_T1&, _U1>,
1276  is_nothrow_assignable<_T2&, _U2>>::value;
1277  }
1278 
1279  template<typename _U1, typename _U2>
1280  static constexpr bool __nothrow_constructible()
1281  {
1282  return __and_<is_nothrow_constructible<_T1, _U1>,
1283  is_nothrow_constructible<_T2, _U2>>::value;
1284  }
1285 
1286  static constexpr bool __nothrow_default_constructible()
1287  {
1288  return __and_<is_nothrow_default_constructible<_T1>,
1289  is_nothrow_default_constructible<_T2>>::value;
1290  }
1291 
1292  template<typename _U1>
1293  static constexpr bool __is_alloc_arg()
1294  { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
1295 
1296 #if __cplusplus > 202002L
1297  template<typename _U1, typename _U2>
1298  static constexpr bool __constructible
1299  = _TCC<true>::template __constructible<_U1, _U2>::value;
1300 
1301  template<typename _U1, typename _U2>
1302  static constexpr bool __convertible
1303  = _TCC<true>::template __convertible<_U1, _U2>::value;
1304 #endif // C++23
1305 
1306  public:
1307  template<bool _Dummy = true,
1308  _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
1309  constexpr
1310  tuple()
1311  noexcept(__nothrow_default_constructible())
1312  : _Inherited() { }
1313 
1314  template<bool _Dummy = true,
1315  _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
1316  explicit constexpr
1317  tuple()
1318  noexcept(__nothrow_default_constructible())
1319  : _Inherited() { }
1320 
1321  template<bool _Dummy = true,
1322  _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
1323  constexpr
1324  tuple(const _T1& __a1, const _T2& __a2)
1325  noexcept(__nothrow_constructible<const _T1&, const _T2&>())
1326  : _Inherited(__a1, __a2) { }
1327 
1328  template<bool _Dummy = true,
1329  _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
1330  explicit constexpr
1331  tuple(const _T1& __a1, const _T2& __a2)
1332  noexcept(__nothrow_constructible<const _T1&, const _T2&>())
1333  : _Inherited(__a1, __a2) { }
1334 
1335  template<typename _U1, typename _U2,
1336  _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
1337  constexpr
1338  tuple(_U1&& __a1, _U2&& __a2)
1339  noexcept(__nothrow_constructible<_U1, _U2>())
1340  : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
1341 
1342  template<typename _U1, typename _U2,
1343  _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
1344  explicit constexpr
1345  tuple(_U1&& __a1, _U2&& __a2)
1346  noexcept(__nothrow_constructible<_U1, _U2>())
1347  : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
1348 
1349  constexpr tuple(const tuple&) = default;
1350 
1351  constexpr tuple(tuple&&) = default;
1352 
1353  template<typename _U1, typename _U2,
1354  _ImplicitCtor<true, const _U1&, const _U2&> = true>
1355  constexpr
1356  tuple(const tuple<_U1, _U2>& __in)
1357  noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1358  : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
1359 
1360  template<typename _U1, typename _U2,
1361  _ExplicitCtor<true, const _U1&, const _U2&> = false>
1362  explicit constexpr
1363  tuple(const tuple<_U1, _U2>& __in)
1364  noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1365  : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
1366 
1367  template<typename _U1, typename _U2,
1368  _ImplicitCtor<true, _U1, _U2> = true>
1369  constexpr
1370  tuple(tuple<_U1, _U2>&& __in)
1371  noexcept(__nothrow_constructible<_U1, _U2>())
1372  : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
1373 
1374  template<typename _U1, typename _U2,
1375  _ExplicitCtor<true, _U1, _U2> = false>
1376  explicit constexpr
1377  tuple(tuple<_U1, _U2>&& __in)
1378  noexcept(__nothrow_constructible<_U1, _U2>())
1379  : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
1380 
1381 #if __cplusplus > 202002L
1382  template<typename _U1, typename _U2>
1383  requires __constructible<_U1&, _U2&>
1384  explicit(!__convertible<_U1&, _U2&>)
1385  constexpr
1386  tuple(tuple<_U1, _U2>& __in)
1387  noexcept(__nothrow_constructible<_U1&, _U2&>())
1388  : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&>(__in)) { }
1389 
1390  template<typename _U1, typename _U2>
1391  requires __constructible<const _U1, const _U2>
1392  explicit(!__convertible<const _U1, const _U2>)
1393  constexpr
1394  tuple(const tuple<_U1, _U2>&& __in)
1395  noexcept(__nothrow_constructible<const _U1, const _U2>())
1396  : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&&>(__in)) { }
1397 #endif // C++23
1398 
1399  template<typename _U1, typename _U2,
1400  _ImplicitCtor<true, const _U1&, const _U2&> = true>
1401  constexpr
1402  tuple(const pair<_U1, _U2>& __in)
1403  noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1404  : _Inherited(__in.first, __in.second) { }
1405 
1406  template<typename _U1, typename _U2,
1407  _ExplicitCtor<true, const _U1&, const _U2&> = false>
1408  explicit constexpr
1409  tuple(const pair<_U1, _U2>& __in)
1410  noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1411  : _Inherited(__in.first, __in.second) { }
1412 
1413  template<typename _U1, typename _U2,
1414  _ImplicitCtor<true, _U1, _U2> = true>
1415  constexpr
1416  tuple(pair<_U1, _U2>&& __in)
1417  noexcept(__nothrow_constructible<_U1, _U2>())
1418  : _Inherited(std::forward<_U1>(__in.first),
1419  std::forward<_U2>(__in.second)) { }
1420 
1421  template<typename _U1, typename _U2,
1422  _ExplicitCtor<true, _U1, _U2> = false>
1423  explicit constexpr
1424  tuple(pair<_U1, _U2>&& __in)
1425  noexcept(__nothrow_constructible<_U1, _U2>())
1426  : _Inherited(std::forward<_U1>(__in.first),
1427  std::forward<_U2>(__in.second)) { }
1428 
1429 #if __cplusplus > 202002L
1430  template<typename _U1, typename _U2>
1431  requires __constructible<_U1&, _U2&>
1432  explicit(!__convertible<_U1&, _U2&>)
1433  constexpr
1434  tuple(pair<_U1, _U2>& __in)
1435  noexcept(__nothrow_constructible<_U1&, _U2&>())
1436  : _Inherited(__in.first, __in.second) { }
1437 
1438  template<typename _U1, typename _U2>
1439  requires __constructible<const _U1, const _U2>
1440  explicit(!__convertible<const _U1, const _U2>)
1441  constexpr
1442  tuple(const pair<_U1, _U2>&& __in)
1443  noexcept(__nothrow_constructible<const _U1, const _U2>())
1444  : _Inherited(std::forward<const _U1>(__in.first),
1445  std::forward<const _U2>(__in.second)) { }
1446 #endif // C++23
1447 
1448  // Allocator-extended constructors.
1449 
1450  template<typename _Alloc,
1451  _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
1452  _GLIBCXX20_CONSTEXPR
1453  tuple(allocator_arg_t __tag, const _Alloc& __a)
1454  : _Inherited(__tag, __a) { }
1455 
1456  template<typename _Alloc, bool _Dummy = true,
1457  _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
1458  _GLIBCXX20_CONSTEXPR
1459  tuple(allocator_arg_t __tag, const _Alloc& __a,
1460  const _T1& __a1, const _T2& __a2)
1461  : _Inherited(__tag, __a, __a1, __a2) { }
1462 
1463  template<typename _Alloc, bool _Dummy = true,
1464  _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
1465  explicit
1466  _GLIBCXX20_CONSTEXPR
1467  tuple(allocator_arg_t __tag, const _Alloc& __a,
1468  const _T1& __a1, const _T2& __a2)
1469  : _Inherited(__tag, __a, __a1, __a2) { }
1470 
1471  template<typename _Alloc, typename _U1, typename _U2,
1472  _ImplicitCtor<true, _U1, _U2> = true>
1473  _GLIBCXX20_CONSTEXPR
1474  tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
1475  : _Inherited(__tag, __a, std::forward<_U1>(__a1),
1476  std::forward<_U2>(__a2)) { }
1477 
1478  template<typename _Alloc, typename _U1, typename _U2,
1479  _ExplicitCtor<true, _U1, _U2> = false>
1480  explicit
1481  _GLIBCXX20_CONSTEXPR
1482  tuple(allocator_arg_t __tag, const _Alloc& __a,
1483  _U1&& __a1, _U2&& __a2)
1484  : _Inherited(__tag, __a, std::forward<_U1>(__a1),
1485  std::forward<_U2>(__a2)) { }
1486 
1487  template<typename _Alloc>
1488  _GLIBCXX20_CONSTEXPR
1489  tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1490  : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1491 
1492  template<typename _Alloc>
1493  _GLIBCXX20_CONSTEXPR
1494  tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1495  : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1496 
1497  template<typename _Alloc, typename _U1, typename _U2,
1498  _ImplicitCtor<true, const _U1&, const _U2&> = true>
1499  _GLIBCXX20_CONSTEXPR
1500  tuple(allocator_arg_t __tag, const _Alloc& __a,
1501  const tuple<_U1, _U2>& __in)
1502  : _Inherited(__tag, __a,
1503  static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
1504  { }
1505 
1506  template<typename _Alloc, typename _U1, typename _U2,
1507  _ExplicitCtor<true, const _U1&, const _U2&> = false>
1508  explicit
1509  _GLIBCXX20_CONSTEXPR
1510  tuple(allocator_arg_t __tag, const _Alloc& __a,
1511  const tuple<_U1, _U2>& __in)
1512  : _Inherited(__tag, __a,
1513  static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
1514  { }
1515 
1516  template<typename _Alloc, typename _U1, typename _U2,
1517  _ImplicitCtor<true, _U1, _U2> = true>
1518  _GLIBCXX20_CONSTEXPR
1519  tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
1520  : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
1521  { }
1522 
1523  template<typename _Alloc, typename _U1, typename _U2,
1524  _ExplicitCtor<true, _U1, _U2> = false>
1525  explicit
1526  _GLIBCXX20_CONSTEXPR
1527  tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
1528  : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
1529  { }
1530 
1531 #if __cplusplus > 202002L
1532  template<typename _Alloc, typename _U1, typename _U2>
1533  requires __constructible<_U1&, _U2&>
1534  explicit(!__convertible<_U1&, _U2&>)
1535  constexpr
1536  tuple(allocator_arg_t __tag, const _Alloc& __a,
1537  tuple<_U1, _U2>& __in)
1538  : _Inherited(__tag, __a,
1539  static_cast<_Tuple_impl<0, _U1, _U2>&>(__in))
1540  { }
1541 
1542  template<typename _Alloc, typename _U1, typename _U2>
1543  requires __constructible<const _U1, const _U2>
1544  explicit(!__convertible<const _U1, const _U2>)
1545  constexpr
1546  tuple(allocator_arg_t __tag, const _Alloc& __a,
1547  const tuple<_U1, _U2>&& __in)
1548  : _Inherited(__tag, __a,
1549  static_cast<const _Tuple_impl<0, _U1, _U2>&&>(__in))
1550  { }
1551 #endif // C++23
1552 
1553  template<typename _Alloc, typename _U1, typename _U2,
1554  _ImplicitCtor<true, const _U1&, const _U2&> = true>
1555  _GLIBCXX20_CONSTEXPR
1556  tuple(allocator_arg_t __tag, const _Alloc& __a,
1557  const pair<_U1, _U2>& __in)
1558  : _Inherited(__tag, __a, __in.first, __in.second) { }
1559 
1560  template<typename _Alloc, typename _U1, typename _U2,
1561  _ExplicitCtor<true, const _U1&, const _U2&> = false>
1562  explicit
1563  _GLIBCXX20_CONSTEXPR
1564  tuple(allocator_arg_t __tag, const _Alloc& __a,
1565  const pair<_U1, _U2>& __in)
1566  : _Inherited(__tag, __a, __in.first, __in.second) { }
1567 
1568  template<typename _Alloc, typename _U1, typename _U2,
1569  _ImplicitCtor<true, _U1, _U2> = true>
1570  _GLIBCXX20_CONSTEXPR
1571  tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
1572  : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
1573  std::forward<_U2>(__in.second)) { }
1574 
1575  template<typename _Alloc, typename _U1, typename _U2,
1576  _ExplicitCtor<true, _U1, _U2> = false>
1577  explicit
1578  _GLIBCXX20_CONSTEXPR
1579  tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
1580  : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
1581  std::forward<_U2>(__in.second)) { }
1582 
1583 #if __cplusplus > 202002L
1584  template<typename _Alloc, typename _U1, typename _U2>
1585  requires __constructible<_U1&, _U2&>
1586  explicit(!__convertible<_U1&, _U2&>)
1587  constexpr
1588  tuple(allocator_arg_t __tag, const _Alloc& __a,
1589  pair<_U1, _U2>& __in)
1590  : _Inherited(__tag, __a, __in.first, __in.second) { }
1591 
1592  template<typename _Alloc, typename _U1, typename _U2>
1593  requires __constructible<const _U1, const _U2>
1594  explicit(!__convertible<const _U1, const _U2>)
1595  constexpr
1596  tuple(allocator_arg_t __tag, const _Alloc& __a, const pair<_U1, _U2>&& __in)
1597  : _Inherited(__tag, __a, std::forward<const _U1>(__in.first),
1598  std::forward<const _U2>(__in.second)) { }
1599 #endif // C++23
1600 
1601  // Tuple assignment.
1602 
1603  _GLIBCXX20_CONSTEXPR
1604  tuple&
1605  operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
1606  const tuple&,
1607  const __nonesuch&> __in)
1608  noexcept(__nothrow_assignable<const _T1&, const _T2&>())
1609  {
1610  this->_M_assign(__in);
1611  return *this;
1612  }
1613 
1614  _GLIBCXX20_CONSTEXPR
1615  tuple&
1616  operator=(__conditional_t<__assignable<_T1, _T2>(),
1617  tuple&&,
1618  __nonesuch&&> __in)
1619  noexcept(__nothrow_assignable<_T1, _T2>())
1620  {
1621  this->_M_assign(std::move(__in));
1622  return *this;
1623  }
1624 
1625  template<typename _U1, typename _U2>
1626  _GLIBCXX20_CONSTEXPR
1627  __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
1628  operator=(const tuple<_U1, _U2>& __in)
1629  noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1630  {
1631  this->_M_assign(__in);
1632  return *this;
1633  }
1634 
1635  template<typename _U1, typename _U2>
1636  _GLIBCXX20_CONSTEXPR
1637  __enable_if_t<__assignable<_U1, _U2>(), tuple&>
1638  operator=(tuple<_U1, _U2>&& __in)
1639  noexcept(__nothrow_assignable<_U1, _U2>())
1640  {
1641  this->_M_assign(std::move(__in));
1642  return *this;
1643  }
1644 
1645 #if __cplusplus > 202002L
1646  constexpr const tuple&
1647  operator=(const tuple& __in) const
1648  requires is_copy_assignable_v<const _T1> && is_copy_assignable_v<const _T2>
1649  {
1650  this->_M_assign(__in);
1651  return *this;
1652  }
1653 
1654  constexpr const tuple&
1655  operator=(tuple&& __in) const
1656  requires is_assignable_v<const _T1&, _T1> && is_assignable_v<const _T2, _T2>
1657  {
1658  this->_M_assign(std::move(__in));
1659  return *this;
1660  }
1661 
1662  template<typename _U1, typename _U2>
1663  constexpr const tuple&
1664  operator=(const tuple<_U1, _U2>& __in) const
1665  requires is_assignable_v<const _T1&, const _U1&>
1666  && is_assignable_v<const _T2&, const _U2&>
1667  {
1668  this->_M_assign(__in);
1669  return *this;
1670  }
1671 
1672  template<typename _U1, typename _U2>
1673  constexpr const tuple&
1674  operator=(tuple<_U1, _U2>&& __in) const
1675  requires is_assignable_v<const _T1&, _U1>
1676  && is_assignable_v<const _T2&, _U2>
1677  {
1678  this->_M_assign(std::move(__in));
1679  return *this;
1680  }
1681 #endif // C++23
1682 
1683  template<typename _U1, typename _U2>
1684  _GLIBCXX20_CONSTEXPR
1685  __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
1686  operator=(const pair<_U1, _U2>& __in)
1687  noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1688  {
1689  this->_M_head(*this) = __in.first;
1690  this->_M_tail(*this)._M_head(*this) = __in.second;
1691  return *this;
1692  }
1693 
1694  template<typename _U1, typename _U2>
1695  _GLIBCXX20_CONSTEXPR
1696  __enable_if_t<__assignable<_U1, _U2>(), tuple&>
1697  operator=(pair<_U1, _U2>&& __in)
1698  noexcept(__nothrow_assignable<_U1, _U2>())
1699  {
1700  this->_M_head(*this) = std::forward<_U1>(__in.first);
1701  this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
1702  return *this;
1703  }
1704 
1705 #if __cplusplus > 202002L
1706  template<typename _U1, typename _U2>
1707  constexpr const tuple&
1708  operator=(const pair<_U1, _U2>& __in) const
1709  requires is_assignable_v<const _T1&, const _U1&>
1710  && is_assignable_v<const _T2&, const _U2&>
1711  {
1712  this->_M_head(*this) = __in.first;
1713  this->_M_tail(*this)._M_head(*this) = __in.second;
1714  return *this;
1715  }
1716 
1717  template<typename _U1, typename _U2>
1718  constexpr const tuple&
1719  operator=(pair<_U1, _U2>&& __in) const
1720  requires is_assignable_v<const _T1&, _U1>
1721  && is_assignable_v<const _T2&, _U2>
1722  {
1723  this->_M_head(*this) = std::forward<_U1>(__in.first);
1724  this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
1725  return *this;
1726  }
1727 #endif // C++23
1728 
1729  _GLIBCXX20_CONSTEXPR
1730  void
1731  swap(tuple& __in)
1732  noexcept(__and_<__is_nothrow_swappable<_T1>,
1733  __is_nothrow_swappable<_T2>>::value)
1734  { _Inherited::_M_swap(__in); }
1735 
1736 #if __cplusplus > 202002L
1737  constexpr void
1738  swap(const tuple& __in) const
1739  noexcept(__and_v<__is_nothrow_swappable<const _T1>,
1740  __is_nothrow_swappable<const _T2>>)
1741  requires is_swappable_v<const _T1> && is_swappable_v<const _T2>
1742  { _Inherited::_M_swap(__in); }
1743 #endif // C++23
1744  };
1745 
1746 
1747  /// class tuple_size
1748  template<typename... _Elements>
1749  struct tuple_size<tuple<_Elements...>>
1750  : public integral_constant<size_t, sizeof...(_Elements)> { };
1751 
1752 #if __cplusplus >= 201703L
1753  template<typename... _Types>
1754  inline constexpr size_t tuple_size_v<tuple<_Types...>>
1755  = sizeof...(_Types);
1756 
1757  template<typename... _Types>
1758  inline constexpr size_t tuple_size_v<const tuple<_Types...>>
1759  = sizeof...(_Types);
1760 #endif
1761 
1762  /// Trait to get the Ith element type from a tuple.
1763  template<size_t __i, typename... _Types>
1764  struct tuple_element<__i, tuple<_Types...>>
1765  {
1766  static_assert(__i < sizeof...(_Types), "tuple index must be in range");
1767 
1768  using type = typename _Nth_type<__i, _Types...>::type;
1769  };
1770 
1771  template<size_t __i, typename _Head, typename... _Tail>
1772  constexpr _Head&
1773  __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
1774  { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
1775 
1776  template<size_t __i, typename _Head, typename... _Tail>
1777  constexpr const _Head&
1778  __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
1779  { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
1780 
1781  // Deleted overload to improve diagnostics for invalid indices
1782  template<size_t __i, typename... _Types>
1783  __enable_if_t<(__i >= sizeof...(_Types))>
1784  __get_helper(const tuple<_Types...>&) = delete;
1785 
1786  /// Return a reference to the ith element of a tuple.
1787  template<size_t __i, typename... _Elements>
1788  constexpr __tuple_element_t<__i, tuple<_Elements...>>&
1789  get(tuple<_Elements...>& __t) noexcept
1790  { return std::__get_helper<__i>(__t); }
1791 
1792  /// Return a const reference to the ith element of a const tuple.
1793  template<size_t __i, typename... _Elements>
1794  constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
1795  get(const tuple<_Elements...>& __t) noexcept
1796  { return std::__get_helper<__i>(__t); }
1797 
1798  /// Return an rvalue reference to the ith element of a tuple rvalue.
1799  template<size_t __i, typename... _Elements>
1800  constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
1801  get(tuple<_Elements...>&& __t) noexcept
1802  {
1803  typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
1804  return std::forward<__element_type>(std::__get_helper<__i>(__t));
1805  }
1806 
1807  /// Return a const rvalue reference to the ith element of a const tuple rvalue.
1808  template<size_t __i, typename... _Elements>
1809  constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
1810  get(const tuple<_Elements...>&& __t) noexcept
1811  {
1812  typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
1813  return std::forward<const __element_type>(std::__get_helper<__i>(__t));
1814  }
1815 
1816  /// @cond undocumented
1817  // Deleted overload chosen for invalid indices.
1818  template<size_t __i, typename... _Elements>
1819  constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
1820  get(const tuple<_Elements...>&) = delete;
1821  /// @endcond
1822 
1823 #if __cplusplus >= 201402L
1824 
1825 #define __cpp_lib_tuples_by_type 201304L
1826 
1827  /// Return a reference to the unique element of type _Tp of a tuple.
1828  template <typename _Tp, typename... _Types>
1829  constexpr _Tp&
1830  get(tuple<_Types...>& __t) noexcept
1831  {
1832  constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1833  static_assert(__idx < sizeof...(_Types),
1834  "the type T in std::get<T> must occur exactly once in the tuple");
1835  return std::__get_helper<__idx>(__t);
1836  }
1837 
1838  /// Return a reference to the unique element of type _Tp of a tuple rvalue.
1839  template <typename _Tp, typename... _Types>
1840  constexpr _Tp&&
1841  get(tuple<_Types...>&& __t) noexcept
1842  {
1843  constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1844  static_assert(__idx < sizeof...(_Types),
1845  "the type T in std::get<T> must occur exactly once in the tuple");
1846  return std::forward<_Tp>(std::__get_helper<__idx>(__t));
1847  }
1848 
1849  /// Return a const reference to the unique element of type _Tp of a tuple.
1850  template <typename _Tp, typename... _Types>
1851  constexpr const _Tp&
1852  get(const tuple<_Types...>& __t) noexcept
1853  {
1854  constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1855  static_assert(__idx < sizeof...(_Types),
1856  "the type T in std::get<T> must occur exactly once in the tuple");
1857  return std::__get_helper<__idx>(__t);
1858  }
1859 
1860  /// Return a const reference to the unique element of type _Tp of
1861  /// a const tuple rvalue.
1862  template <typename _Tp, typename... _Types>
1863  constexpr const _Tp&&
1864  get(const tuple<_Types...>&& __t) noexcept
1865  {
1866  constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1867  static_assert(__idx < sizeof...(_Types),
1868  "the type T in std::get<T> must occur exactly once in the tuple");
1869  return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
1870  }
1871 #endif
1872 
1873  // This class performs the comparison operations on tuples
1874  template<typename _Tp, typename _Up, size_t __i, size_t __size>
1875  struct __tuple_compare
1876  {
1877  static constexpr bool
1878  __eq(const _Tp& __t, const _Up& __u)
1879  {
1880  return bool(std::get<__i>(__t) == std::get<__i>(__u))
1881  && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
1882  }
1883 
1884  static constexpr bool
1885  __less(const _Tp& __t, const _Up& __u)
1886  {
1887  return bool(std::get<__i>(__t) < std::get<__i>(__u))
1888  || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
1889  && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
1890  }
1891  };
1892 
1893  template<typename _Tp, typename _Up, size_t __size>
1894  struct __tuple_compare<_Tp, _Up, __size, __size>
1895  {
1896  static constexpr bool
1897  __eq(const _Tp&, const _Up&) { return true; }
1898 
1899  static constexpr bool
1900  __less(const _Tp&, const _Up&) { return false; }
1901  };
1902 
1903  template<typename... _TElements, typename... _UElements>
1904  constexpr bool
1905  operator==(const tuple<_TElements...>& __t,
1906  const tuple<_UElements...>& __u)
1907  {
1908  static_assert(sizeof...(_TElements) == sizeof...(_UElements),
1909  "tuple objects can only be compared if they have equal sizes.");
1910  using __compare = __tuple_compare<tuple<_TElements...>,
1911  tuple<_UElements...>,
1912  0, sizeof...(_TElements)>;
1913  return __compare::__eq(__t, __u);
1914  }
1915 
1916 #if __cpp_lib_three_way_comparison
1917  template<typename _Cat, typename _Tp, typename _Up>
1918  constexpr _Cat
1919  __tuple_cmp(const _Tp&, const _Up&, index_sequence<>)
1920  { return _Cat::equivalent; }
1921 
1922  template<typename _Cat, typename _Tp, typename _Up,
1923  size_t _Idx0, size_t... _Idxs>
1924  constexpr _Cat
1925  __tuple_cmp(const _Tp& __t, const _Up& __u,
1926  index_sequence<_Idx0, _Idxs...>)
1927  {
1928  auto __c
1929  = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u));
1930  if (__c != 0)
1931  return __c;
1932  return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>());
1933  }
1934 
1935  template<typename... _Tps, typename... _Ups>
1936  constexpr
1937  common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
1938  operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
1939  {
1940  using _Cat
1941  = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
1942  return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
1943  }
1944 #else
1945  template<typename... _TElements, typename... _UElements>
1946  constexpr bool
1947  operator<(const tuple<_TElements...>& __t,
1948  const tuple<_UElements...>& __u)
1949  {
1950  static_assert(sizeof...(_TElements) == sizeof...(_UElements),
1951  "tuple objects can only be compared if they have equal sizes.");
1952  using __compare = __tuple_compare<tuple<_TElements...>,
1953  tuple<_UElements...>,
1954  0, sizeof...(_TElements)>;
1955  return __compare::__less(__t, __u);
1956  }
1957 
1958  template<typename... _TElements, typename... _UElements>
1959  constexpr bool
1960  operator!=(const tuple<_TElements...>& __t,
1961  const tuple<_UElements...>& __u)
1962  { return !(__t == __u); }
1963 
1964  template<typename... _TElements, typename... _UElements>
1965  constexpr bool
1966  operator>(const tuple<_TElements...>& __t,
1967  const tuple<_UElements...>& __u)
1968  { return __u < __t; }
1969 
1970  template<typename... _TElements, typename... _UElements>
1971  constexpr bool
1972  operator<=(const tuple<_TElements...>& __t,
1973  const tuple<_UElements...>& __u)
1974  { return !(__u < __t); }
1975 
1976  template<typename... _TElements, typename... _UElements>
1977  constexpr bool
1978  operator>=(const tuple<_TElements...>& __t,
1979  const tuple<_UElements...>& __u)
1980  { return !(__t < __u); }
1981 #endif // three_way_comparison
1982 
1983  // NB: DR 705.
1984  /// Create a tuple containing copies of the arguments
1985  template<typename... _Elements>
1986  constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
1987  make_tuple(_Elements&&... __args)
1988  {
1989  typedef tuple<typename __decay_and_strip<_Elements>::__type...>
1990  __result_type;
1991  return __result_type(std::forward<_Elements>(__args)...);
1992  }
1993 
1994  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1995  // 2275. Why is forward_as_tuple not constexpr?
1996  /// Create a tuple of lvalue or rvalue references to the arguments
1997  template<typename... _Elements>
1998  constexpr tuple<_Elements&&...>
1999  forward_as_tuple(_Elements&&... __args) noexcept
2000  { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2001 
2002  // Declarations of std::array and its std::get overloads, so that
2003  // std::tuple_cat can use them if <tuple> is included before <array>.
2004 
2005  template<typename _Tp, size_t _Nm> struct array;
2006 
2007  template<size_t _Int, typename _Tp, size_t _Nm>
2008  constexpr _Tp&
2009  get(array<_Tp, _Nm>&) noexcept;
2010 
2011  template<size_t _Int, typename _Tp, size_t _Nm>
2012  constexpr _Tp&&
2013  get(array<_Tp, _Nm>&&) noexcept;
2014 
2015  template<size_t _Int, typename _Tp, size_t _Nm>
2016  constexpr const _Tp&
2017  get(const array<_Tp, _Nm>&) noexcept;
2018 
2019  template<size_t _Int, typename _Tp, size_t _Nm>
2020  constexpr const _Tp&&
2021  get(const array<_Tp, _Nm>&&) noexcept;
2022 
2023  /// @cond undocumented
2024  template<size_t, typename, typename, size_t>
2025  struct __make_tuple_impl;
2026 
2027  template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
2028  struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
2029  : __make_tuple_impl<_Idx + 1,
2030  tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
2031  _Tuple, _Nm>
2032  { };
2033 
2034  template<size_t _Nm, typename _Tuple, typename... _Tp>
2035  struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
2036  {
2037  typedef tuple<_Tp...> __type;
2038  };
2039 
2040  template<typename _Tuple>
2041  struct __do_make_tuple
2042  : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
2043  { };
2044 
2045  // Returns the std::tuple equivalent of a tuple-like type.
2046  template<typename _Tuple>
2047  struct __make_tuple
2048  : public __do_make_tuple<__remove_cvref_t<_Tuple>>
2049  { };
2050 
2051  // Combines several std::tuple's into a single one.
2052  template<typename...>
2053  struct __combine_tuples;
2054 
2055  template<>
2056  struct __combine_tuples<>
2057  {
2058  typedef tuple<> __type;
2059  };
2060 
2061  template<typename... _Ts>
2062  struct __combine_tuples<tuple<_Ts...>>
2063  {
2064  typedef tuple<_Ts...> __type;
2065  };
2066 
2067  template<typename... _T1s, typename... _T2s, typename... _Rem>
2068  struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
2069  {
2070  typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
2071  _Rem...>::__type __type;
2072  };
2073 
2074  // Computes the result type of tuple_cat given a set of tuple-like types.
2075  template<typename... _Tpls>
2076  struct __tuple_cat_result
2077  {
2078  typedef typename __combine_tuples
2079  <typename __make_tuple<_Tpls>::__type...>::__type __type;
2080  };
2081 
2082  // Helper to determine the index set for the first tuple-like
2083  // type of a given set.
2084  template<typename...>
2085  struct __make_1st_indices;
2086 
2087  template<>
2088  struct __make_1st_indices<>
2089  {
2090  typedef _Index_tuple<> __type;
2091  };
2092 
2093  template<typename _Tp, typename... _Tpls>
2094  struct __make_1st_indices<_Tp, _Tpls...>
2095  {
2096  typedef typename _Build_index_tuple<tuple_size<
2097  typename remove_reference<_Tp>::type>::value>::__type __type;
2098  };
2099 
2100  // Performs the actual concatenation by step-wise expanding tuple-like
2101  // objects into the elements, which are finally forwarded into the
2102  // result tuple.
2103  template<typename _Ret, typename _Indices, typename... _Tpls>
2104  struct __tuple_concater;
2105 
2106  template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2107  struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2108  {
2109  template<typename... _Us>
2110  static constexpr _Ret
2111  _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2112  {
2113  typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2114  typedef __tuple_concater<_Ret, __idx, _Tpls...> __next;
2115  return __next::_S_do(std::forward<_Tpls>(__tps)...,
2116  std::forward<_Us>(__us)...,
2117  std::get<_Is>(std::forward<_Tp>(__tp))...);
2118  }
2119  };
2120 
2121  template<typename _Ret>
2122  struct __tuple_concater<_Ret, _Index_tuple<>>
2123  {
2124  template<typename... _Us>
2125  static constexpr _Ret
2126  _S_do(_Us&&... __us)
2127  {
2128  return _Ret(std::forward<_Us>(__us)...);
2129  }
2130  };
2131 
2132  template<typename... _Tps>
2133  struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2134  { };
2135  /// @endcond
2136 
2137  /// Create a `tuple` containing all elements from multiple tuple-like objects
2138  template<typename... _Tpls, typename = typename
2139  enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2140  constexpr auto
2141  tuple_cat(_Tpls&&... __tpls)
2142  -> typename __tuple_cat_result<_Tpls...>::__type
2143  {
2144  typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2145  typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2146  typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2147  return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2148  }
2149 
2150  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2151  // 2301. Why is tie not constexpr?
2152  /// Return a tuple of lvalue references bound to the arguments
2153  template<typename... _Elements>
2154  constexpr tuple<_Elements&...>
2155  tie(_Elements&... __args) noexcept
2156  { return tuple<_Elements&...>(__args...); }
2157 
2158  /// Exchange the values of two tuples
2159  template<typename... _Elements>
2160  _GLIBCXX20_CONSTEXPR
2161  inline
2162 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2163  // Constrained free swap overload, see p0185r1
2164  typename enable_if<__and_<__is_swappable<_Elements>...>::value
2165  >::type
2166 #else
2167  void
2168 #endif
2169  swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
2170  noexcept(noexcept(__x.swap(__y)))
2171  { __x.swap(__y); }
2172 
2173 #if __cplusplus > 202002L
2174  template<typename... _Elements>
2175  requires (is_swappable_v<const _Elements> && ...)
2176  constexpr void
2177  swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2178  noexcept(noexcept(__x.swap(__y)))
2179  { __x.swap(__y); }
2180 #endif // C++23
2181 
2182 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2183  /// Exchange the values of two const tuples (if const elements can be swapped)
2184  template<typename... _Elements>
2185  _GLIBCXX20_CONSTEXPR
2186  typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2187  swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2188 #endif
2189 
2190  // A class (and instance) which can be used in 'tie' when an element
2191  // of a tuple is not required.
2192  // _GLIBCXX14_CONSTEXPR
2193  // 2933. PR for LWG 2773 could be clearer
2194  struct _Swallow_assign
2195  {
2196  template<class _Tp>
2197  _GLIBCXX14_CONSTEXPR const _Swallow_assign&
2198  operator=(const _Tp&) const
2199  { return *this; }
2200  };
2201 
2202  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2203  // 2773. Making std::ignore constexpr
2204  /** Used with `std::tie` to ignore an element of a tuple
2205  *
2206  * When using `std::tie` to assign the elements of a tuple to variables,
2207  * unwanted elements can be ignored by using `std::ignore`. For example:
2208  *
2209  * ```
2210  * int x, y;
2211  * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3);
2212  * ```
2213  *
2214  * This assignment will perform `x=1; std::ignore=2; y=3;` which results
2215  * in the second element being ignored.
2216  *
2217  * @since C++11
2218  */
2219  _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{};
2220 
2221  /// Partial specialization for tuples
2222  template<typename... _Types, typename _Alloc>
2223  struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2224 
2225  // See stl_pair.h...
2226  /** "piecewise construction" using a tuple of arguments for each member.
2227  *
2228  * @param __first Arguments for the first member of the pair.
2229  * @param __second Arguments for the second member of the pair.
2230  *
2231  * The elements of each tuple will be used as the constructor arguments
2232  * for the data members of the pair.
2233  */
2234  template<class _T1, class _T2>
2235  template<typename... _Args1, typename... _Args2>
2236  _GLIBCXX20_CONSTEXPR
2237  inline
2238  pair<_T1, _T2>::
2239  pair(piecewise_construct_t,
2240  tuple<_Args1...> __first, tuple<_Args2...> __second)
2241  : pair(__first, __second,
2242  typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2243  typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2244  { }
2245 
2246  template<class _T1, class _T2>
2247  template<typename... _Args1, size_t... _Indexes1,
2248  typename... _Args2, size_t... _Indexes2>
2249  _GLIBCXX20_CONSTEXPR inline
2250  pair<_T1, _T2>::
2251  pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2252  _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2253  : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2254  second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2255  { }
2256 
2257 #if __cplusplus >= 201703L
2258 
2259  // Unpack a std::tuple into a type trait and use its value.
2260  // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2261  // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2262  // Otherwise the result is false (because we don't know if std::get throws).
2263  template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2264  inline constexpr bool __unpack_std_tuple = false;
2265 
2266  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2267  inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2268  = _Trait<_Tp, _Up...>::value;
2269 
2270  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2271  inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2272  = _Trait<_Tp, _Up&...>::value;
2273 
2274  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2275  inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2276  = _Trait<_Tp, const _Up...>::value;
2277 
2278  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2279  inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2280  = _Trait<_Tp, const _Up&...>::value;
2281 
2282 # define __cpp_lib_apply 201603L
2283 
2284  template <typename _Fn, typename _Tuple, size_t... _Idx>
2285  constexpr decltype(auto)
2286  __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2287  {
2288  return std::__invoke(std::forward<_Fn>(__f),
2289  std::get<_Idx>(std::forward<_Tuple>(__t))...);
2290  }
2291 
2292  template <typename _Fn, typename _Tuple>
2293  constexpr decltype(auto)
2294  apply(_Fn&& __f, _Tuple&& __t)
2295  noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2296  {
2297  using _Indices
2298  = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2299  return std::__apply_impl(std::forward<_Fn>(__f),
2300  std::forward<_Tuple>(__t),
2301  _Indices{});
2302  }
2303 
2304 #define __cpp_lib_make_from_tuple 201606L
2305 
2306  template <typename _Tp, typename _Tuple, size_t... _Idx>
2307  constexpr _Tp
2308  __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
2309  { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
2310 
2311  template <typename _Tp, typename _Tuple>
2312  constexpr _Tp
2313  make_from_tuple(_Tuple&& __t)
2314  noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
2315  {
2316  constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
2317 #if __has_builtin(__reference_constructs_from_temporary)
2318  if constexpr (__n == 1)
2319  {
2320  using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
2321  static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
2322  }
2323 #endif
2324  return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
2325  make_index_sequence<__n>{});
2326  }
2327 #endif // C++17
2328 
2329 #if __cplusplus > 202002L
2330  template<typename... _TTypes, typename... _UTypes,
2331  template<typename> class _TQual, template<typename> class _UQual>
2332  requires requires { typename tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; }
2333  struct basic_common_reference<tuple<_TTypes...>, tuple<_UTypes...>, _TQual, _UQual>
2334  { using type = tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; };
2335 
2336  template<typename... _TTypes, typename... _UTypes>
2337  requires requires { typename tuple<common_type_t<_TTypes, _UTypes>...>; }
2338  struct common_type<tuple<_TTypes...>, tuple<_UTypes...>>
2339  { using type = tuple<common_type_t<_TTypes, _UTypes>...>; };
2340 #endif // C++23
2341 
2342  /// @}
2343 
2344 _GLIBCXX_END_NAMESPACE_VERSION
2345 } // namespace std
2346 
2347 #endif // C++11
2348 
2349 #endif // _GLIBCXX_TUPLE