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, 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, 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, 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, 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, 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, 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, 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, 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,
975  _ExplicitDefaultCtor<is_object<_Alloc>::value> = false>
976  _GLIBCXX20_CONSTEXPR
977  explicit
978  tuple(allocator_arg_t __tag, const _Alloc& __a)
979  : _Inherited(__tag, __a) { }
980 
981  template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
982  _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
983  _GLIBCXX20_CONSTEXPR
984  tuple(allocator_arg_t __tag, const _Alloc& __a,
985  const _Elements&... __elements)
986  : _Inherited(__tag, __a, __elements...) { }
987 
988  template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
989  _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
990  _GLIBCXX20_CONSTEXPR
991  explicit
992  tuple(allocator_arg_t __tag, const _Alloc& __a,
993  const _Elements&... __elements)
994  : _Inherited(__tag, __a, __elements...) { }
995 
996  template<typename _Alloc, typename... _UElements,
997  bool _Valid = __valid_args<_UElements...>(),
998  _ImplicitCtor<_Valid, _UElements...> = true>
999  _GLIBCXX20_CONSTEXPR
1000  tuple(allocator_arg_t __tag, const _Alloc& __a,
1001  _UElements&&... __elements)
1002  : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1003  { }
1004 
1005  template<typename _Alloc, typename... _UElements,
1006  bool _Valid = __valid_args<_UElements...>(),
1007  _ExplicitCtor<_Valid, _UElements...> = false>
1008  _GLIBCXX20_CONSTEXPR
1009  explicit
1010  tuple(allocator_arg_t __tag, const _Alloc& __a,
1011  _UElements&&... __elements)
1012  : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1013  { }
1014 
1015  template<typename _Alloc>
1016  _GLIBCXX20_CONSTEXPR
1017  tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1018  : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1019 
1020  template<typename _Alloc>
1021  _GLIBCXX20_CONSTEXPR
1022  tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1023  : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1024 
1025  template<typename _Alloc, typename... _UElements,
1026  bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1027  && !__use_other_ctor<const tuple<_UElements...>&>(),
1028  _ImplicitCtor<_Valid, const _UElements&...> = true>
1029  _GLIBCXX20_CONSTEXPR
1030  tuple(allocator_arg_t __tag, const _Alloc& __a,
1031  const tuple<_UElements...>& __in)
1032  : _Inherited(__tag, __a,
1033  static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1034  { }
1035 
1036  template<typename _Alloc, typename... _UElements,
1037  bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1038  && !__use_other_ctor<const tuple<_UElements...>&>(),
1039  _ExplicitCtor<_Valid, const _UElements&...> = false>
1040  _GLIBCXX20_CONSTEXPR
1041  explicit
1042  tuple(allocator_arg_t __tag, const _Alloc& __a,
1043  const tuple<_UElements...>& __in)
1044  : _Inherited(__tag, __a,
1045  static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1046  { }
1047 
1048  template<typename _Alloc, typename... _UElements,
1049  bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1050  && !__use_other_ctor<tuple<_UElements...>&&>(),
1051  _ImplicitCtor<_Valid, _UElements...> = true>
1052  _GLIBCXX20_CONSTEXPR
1053  tuple(allocator_arg_t __tag, const _Alloc& __a,
1054  tuple<_UElements...>&& __in)
1055  : _Inherited(__tag, __a,
1056  static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1057  { }
1058 
1059  template<typename _Alloc, typename... _UElements,
1060  bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1061  && !__use_other_ctor<tuple<_UElements...>&&>(),
1062  _ExplicitCtor<_Valid, _UElements...> = false>
1063  _GLIBCXX20_CONSTEXPR
1064  explicit
1065  tuple(allocator_arg_t __tag, const _Alloc& __a,
1066  tuple<_UElements...>&& __in)
1067  : _Inherited(__tag, __a,
1068  static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1069  { }
1070 
1071 #if __cplusplus > 202002L
1072  template<typename _Alloc, typename... _UElements>
1073  requires (sizeof...(_Elements) == sizeof...(_UElements))
1074  && (!__use_other_ctor<tuple<_UElements...>&>())
1075  && __constructible<_UElements&...>
1076  explicit(!__convertible<_UElements&...>)
1077  constexpr
1078  tuple(allocator_arg_t __tag, const _Alloc& __a,
1079  tuple<_UElements...>& __in)
1080  : _Inherited(__tag, __a,
1081  static_cast<_Tuple_impl<0, _UElements...>&>(__in))
1082  { }
1083 
1084  template<typename _Alloc, typename... _UElements>
1085  requires (sizeof...(_Elements) == sizeof...(_UElements))
1086  && (!__use_other_ctor<const tuple<_UElements...>>())
1087  && __constructible<const _UElements...>
1088  explicit(!__convertible<const _UElements...>)
1089  constexpr
1090  tuple(allocator_arg_t __tag, const _Alloc& __a,
1091  const tuple<_UElements...>&& __in)
1092  : _Inherited(__tag, __a,
1093  static_cast<const _Tuple_impl<0, _UElements...>&&>(__in))
1094  { }
1095 #endif // C++23
1096 
1097  // tuple assignment
1098 
1099  _GLIBCXX20_CONSTEXPR
1100  tuple&
1101  operator=(__conditional_t<__assignable<const _Elements&...>(),
1102  const tuple&,
1103  const __nonesuch&> __in)
1104  noexcept(__nothrow_assignable<const _Elements&...>())
1105  {
1106  this->_M_assign(__in);
1107  return *this;
1108  }
1109 
1110  _GLIBCXX20_CONSTEXPR
1111  tuple&
1112  operator=(__conditional_t<__assignable<_Elements...>(),
1113  tuple&&,
1114  __nonesuch&&> __in)
1115  noexcept(__nothrow_assignable<_Elements...>())
1116  {
1117  this->_M_assign(std::move(__in));
1118  return *this;
1119  }
1120 
1121  template<typename... _UElements>
1122  _GLIBCXX20_CONSTEXPR
1123  __enable_if_t<__assignable<const _UElements&...>(), tuple&>
1124  operator=(const tuple<_UElements...>& __in)
1125  noexcept(__nothrow_assignable<const _UElements&...>())
1126  {
1127  this->_M_assign(__in);
1128  return *this;
1129  }
1130 
1131  template<typename... _UElements>
1132  _GLIBCXX20_CONSTEXPR
1133  __enable_if_t<__assignable<_UElements...>(), tuple&>
1134  operator=(tuple<_UElements...>&& __in)
1135  noexcept(__nothrow_assignable<_UElements...>())
1136  {
1137  this->_M_assign(std::move(__in));
1138  return *this;
1139  }
1140 
1141 #if __cplusplus > 202002L
1142  constexpr const tuple&
1143  operator=(const tuple& __in) const
1144  requires (is_copy_assignable_v<const _Elements> && ...)
1145  {
1146  this->_M_assign(__in);
1147  return *this;
1148  }
1149 
1150  constexpr const tuple&
1151  operator=(tuple&& __in) const
1152  requires (is_assignable_v<const _Elements&, _Elements> && ...)
1153  {
1154  this->_M_assign(std::move(__in));
1155  return *this;
1156  }
1157 
1158  template<typename... _UElements>
1159  constexpr const tuple&
1160  operator=(const tuple<_UElements...>& __in) const
1161  requires (sizeof...(_Elements) == sizeof...(_UElements))
1162  && (is_assignable_v<const _Elements&, const _UElements&> && ...)
1163  {
1164  this->_M_assign(__in);
1165  return *this;
1166  }
1167 
1168  template<typename... _UElements>
1169  constexpr const tuple&
1170  operator=(tuple<_UElements...>&& __in) const
1171  requires (sizeof...(_Elements) == sizeof...(_UElements))
1172  && (is_assignable_v<const _Elements&, _UElements> && ...)
1173  {
1174  this->_M_assign(std::move(__in));
1175  return *this;
1176  }
1177 #endif // C++23
1178 
1179  // tuple swap
1180  _GLIBCXX20_CONSTEXPR
1181  void
1182  swap(tuple& __in)
1183  noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
1184  { _Inherited::_M_swap(__in); }
1185 
1186 #if __cplusplus > 202002L
1187  // As an extension, we constrain the const swap member function in order
1188  // to continue accepting explicit instantiation of tuples whose elements
1189  // are not all const swappable. Without this constraint, such an
1190  // explicit instantiation would also instantiate the ill-formed body of
1191  // this function and yield a hard error. This constraint shouldn't
1192  // affect the behavior of valid programs.
1193  constexpr void
1194  swap(const tuple& __in) const
1195  noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
1196  requires (is_swappable_v<const _Elements> && ...)
1197  { _Inherited::_M_swap(__in); }
1198 #endif // C++23
1199  };
1200 
1201 #if __cpp_deduction_guides >= 201606
1202  template<typename... _UTypes>
1203  tuple(_UTypes...) -> tuple<_UTypes...>;
1204  template<typename _T1, typename _T2>
1205  tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
1206  template<typename _Alloc, typename... _UTypes>
1207  tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
1208  template<typename _Alloc, typename _T1, typename _T2>
1209  tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
1210  template<typename _Alloc, typename... _UTypes>
1211  tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
1212 #endif
1213 
1214  // Explicit specialization, zero-element tuple.
1215  template<>
1216  class tuple<>
1217  {
1218  public:
1219  _GLIBCXX20_CONSTEXPR
1220  void swap(tuple&) noexcept { /* no-op */ }
1221 #if __cplusplus > 202002L
1222  constexpr void swap(const tuple&) const noexcept { /* no-op */ }
1223 #endif
1224  // We need the default since we're going to define no-op
1225  // allocator constructors.
1226  tuple() = default;
1227  // No-op allocator constructors.
1228  template<typename _Alloc>
1229  _GLIBCXX20_CONSTEXPR
1230  tuple(allocator_arg_t, const _Alloc&) noexcept { }
1231  template<typename _Alloc>
1232  _GLIBCXX20_CONSTEXPR
1233  tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
1234  };
1235 
1236  /// Partial specialization, 2-element tuple.
1237  /// Includes construction and assignment from a pair.
1238  template<typename _T1, typename _T2>
1239  class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
1240  {
1241  typedef _Tuple_impl<0, _T1, _T2> _Inherited;
1242 
1243  // Constraint for non-explicit default constructor
1244  template<bool _Dummy, typename _U1, typename _U2>
1245  using _ImplicitDefaultCtor = __enable_if_t<
1246  _TupleConstraints<_Dummy, _U1, _U2>::
1247  __is_implicitly_default_constructible(),
1248  bool>;
1249 
1250  // Constraint for explicit default constructor
1251  template<bool _Dummy, typename _U1, typename _U2>
1252  using _ExplicitDefaultCtor = __enable_if_t<
1253  _TupleConstraints<_Dummy, _U1, _U2>::
1254  __is_explicitly_default_constructible(),
1255  bool>;
1256 
1257  template<bool _Dummy>
1258  using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
1259 
1260  // Constraint for non-explicit constructors
1261  template<bool _Cond, typename _U1, typename _U2>
1262  using _ImplicitCtor = __enable_if_t<
1263  _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
1264  bool>;
1265 
1266  // Constraint for non-explicit constructors
1267  template<bool _Cond, typename _U1, typename _U2>
1268  using _ExplicitCtor = __enable_if_t<
1269  _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
1270  bool>;
1271 
1272  template<typename _U1, typename _U2>
1273  static constexpr bool __assignable()
1274  {
1275  return __and_<is_assignable<_T1&, _U1>,
1276  is_assignable<_T2&, _U2>>::value;
1277  }
1278 
1279  template<typename _U1, typename _U2>
1280  static constexpr bool __nothrow_assignable()
1281  {
1282  return __and_<is_nothrow_assignable<_T1&, _U1>,
1283  is_nothrow_assignable<_T2&, _U2>>::value;
1284  }
1285 
1286  template<typename _U1, typename _U2>
1287  static constexpr bool __nothrow_constructible()
1288  {
1289  return __and_<is_nothrow_constructible<_T1, _U1>,
1290  is_nothrow_constructible<_T2, _U2>>::value;
1291  }
1292 
1293  static constexpr bool __nothrow_default_constructible()
1294  {
1295  return __and_<is_nothrow_default_constructible<_T1>,
1296  is_nothrow_default_constructible<_T2>>::value;
1297  }
1298 
1299  template<typename _U1>
1300  static constexpr bool __is_alloc_arg()
1301  { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
1302 
1303 #if __cplusplus > 202002L
1304  template<typename _U1, typename _U2>
1305  static constexpr bool __constructible
1306  = _TCC<true>::template __constructible<_U1, _U2>::value;
1307 
1308  template<typename _U1, typename _U2>
1309  static constexpr bool __convertible
1310  = _TCC<true>::template __convertible<_U1, _U2>::value;
1311 #endif // C++23
1312 
1313  public:
1314  template<bool _Dummy = true,
1315  _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
1316  constexpr
1317  tuple()
1318  noexcept(__nothrow_default_constructible())
1319  : _Inherited() { }
1320 
1321  template<bool _Dummy = true,
1322  _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
1323  explicit constexpr
1324  tuple()
1325  noexcept(__nothrow_default_constructible())
1326  : _Inherited() { }
1327 
1328  template<bool _Dummy = true,
1329  _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
1330  constexpr
1331  tuple(const _T1& __a1, const _T2& __a2)
1332  noexcept(__nothrow_constructible<const _T1&, const _T2&>())
1333  : _Inherited(__a1, __a2) { }
1334 
1335  template<bool _Dummy = true,
1336  _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
1337  explicit constexpr
1338  tuple(const _T1& __a1, const _T2& __a2)
1339  noexcept(__nothrow_constructible<const _T1&, const _T2&>())
1340  : _Inherited(__a1, __a2) { }
1341 
1342  template<typename _U1, typename _U2,
1343  _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
1344  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  template<typename _U1, typename _U2,
1350  _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
1351  explicit constexpr
1352  tuple(_U1&& __a1, _U2&& __a2)
1353  noexcept(__nothrow_constructible<_U1, _U2>())
1354  : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
1355 
1356  constexpr tuple(const tuple&) = default;
1357 
1358  constexpr tuple(tuple&&) = default;
1359 
1360  template<typename _U1, typename _U2,
1361  _ImplicitCtor<true, const _U1&, const _U2&> = true>
1362  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  _ExplicitCtor<true, const _U1&, const _U2&> = false>
1369  explicit constexpr
1370  tuple(const tuple<_U1, _U2>& __in)
1371  noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1372  : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
1373 
1374  template<typename _U1, typename _U2,
1375  _ImplicitCtor<true, _U1, _U2> = true>
1376  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  template<typename _U1, typename _U2,
1382  _ExplicitCtor<true, _U1, _U2> = false>
1383  explicit constexpr
1384  tuple(tuple<_U1, _U2>&& __in)
1385  noexcept(__nothrow_constructible<_U1, _U2>())
1386  : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
1387 
1388 #if __cplusplus > 202002L
1389  template<typename _U1, typename _U2>
1390  requires __constructible<_U1&, _U2&>
1391  explicit(!__convertible<_U1&, _U2&>)
1392  constexpr
1393  tuple(tuple<_U1, _U2>& __in)
1394  noexcept(__nothrow_constructible<_U1&, _U2&>())
1395  : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&>(__in)) { }
1396 
1397  template<typename _U1, typename _U2>
1398  requires __constructible<const _U1, const _U2>
1399  explicit(!__convertible<const _U1, const _U2>)
1400  constexpr
1401  tuple(const tuple<_U1, _U2>&& __in)
1402  noexcept(__nothrow_constructible<const _U1, const _U2>())
1403  : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&&>(__in)) { }
1404 #endif // C++23
1405 
1406  template<typename _U1, typename _U2,
1407  _ImplicitCtor<true, const _U1&, const _U2&> = true>
1408  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  _ExplicitCtor<true, const _U1&, const _U2&> = false>
1415  explicit constexpr
1416  tuple(const pair<_U1, _U2>& __in)
1417  noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1418  : _Inherited(__in.first, __in.second) { }
1419 
1420  template<typename _U1, typename _U2,
1421  _ImplicitCtor<true, _U1, _U2> = true>
1422  constexpr
1423  tuple(pair<_U1, _U2>&& __in)
1424  noexcept(__nothrow_constructible<_U1, _U2>())
1425  : _Inherited(std::forward<_U1>(__in.first),
1426  std::forward<_U2>(__in.second)) { }
1427 
1428  template<typename _U1, typename _U2,
1429  _ExplicitCtor<true, _U1, _U2> = false>
1430  explicit constexpr
1431  tuple(pair<_U1, _U2>&& __in)
1432  noexcept(__nothrow_constructible<_U1, _U2>())
1433  : _Inherited(std::forward<_U1>(__in.first),
1434  std::forward<_U2>(__in.second)) { }
1435 
1436 #if __cplusplus > 202002L
1437  template<typename _U1, typename _U2>
1438  requires __constructible<_U1&, _U2&>
1439  explicit(!__convertible<_U1&, _U2&>)
1440  constexpr
1441  tuple(pair<_U1, _U2>& __in)
1442  noexcept(__nothrow_constructible<_U1&, _U2&>())
1443  : _Inherited(__in.first, __in.second) { }
1444 
1445  template<typename _U1, typename _U2>
1446  requires __constructible<const _U1, const _U2>
1447  explicit(!__convertible<const _U1, const _U2>)
1448  constexpr
1449  tuple(const pair<_U1, _U2>&& __in)
1450  noexcept(__nothrow_constructible<const _U1, const _U2>())
1451  : _Inherited(std::forward<const _U1>(__in.first),
1452  std::forward<const _U2>(__in.second)) { }
1453 #endif // C++23
1454 
1455  // Allocator-extended constructors.
1456 
1457  template<typename _Alloc,
1458  _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
1459  _GLIBCXX20_CONSTEXPR
1460  tuple(allocator_arg_t __tag, const _Alloc& __a)
1461  : _Inherited(__tag, __a) { }
1462 
1463  template<typename _Alloc,
1464  _ExplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = false>
1465  _GLIBCXX20_CONSTEXPR
1466  explicit
1467  tuple(allocator_arg_t __tag, const _Alloc& __a)
1468  : _Inherited(__tag, __a) { }
1469 
1470  template<typename _Alloc, bool _Dummy = true,
1471  _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
1472  _GLIBCXX20_CONSTEXPR
1473  tuple(allocator_arg_t __tag, const _Alloc& __a,
1474  const _T1& __a1, const _T2& __a2)
1475  : _Inherited(__tag, __a, __a1, __a2) { }
1476 
1477  template<typename _Alloc, bool _Dummy = true,
1478  _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
1479  explicit
1480  _GLIBCXX20_CONSTEXPR
1481  tuple(allocator_arg_t __tag, const _Alloc& __a,
1482  const _T1& __a1, const _T2& __a2)
1483  : _Inherited(__tag, __a, __a1, __a2) { }
1484 
1485  template<typename _Alloc, typename _U1, typename _U2,
1486  _ImplicitCtor<true, _U1, _U2> = true>
1487  _GLIBCXX20_CONSTEXPR
1488  tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
1489  : _Inherited(__tag, __a, std::forward<_U1>(__a1),
1490  std::forward<_U2>(__a2)) { }
1491 
1492  template<typename _Alloc, typename _U1, typename _U2,
1493  _ExplicitCtor<true, _U1, _U2> = false>
1494  explicit
1495  _GLIBCXX20_CONSTEXPR
1496  tuple(allocator_arg_t __tag, const _Alloc& __a,
1497  _U1&& __a1, _U2&& __a2)
1498  : _Inherited(__tag, __a, std::forward<_U1>(__a1),
1499  std::forward<_U2>(__a2)) { }
1500 
1501  template<typename _Alloc>
1502  _GLIBCXX20_CONSTEXPR
1503  tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1504  : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1505 
1506  template<typename _Alloc>
1507  _GLIBCXX20_CONSTEXPR
1508  tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1509  : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1510 
1511  template<typename _Alloc, typename _U1, typename _U2,
1512  _ImplicitCtor<true, const _U1&, const _U2&> = true>
1513  _GLIBCXX20_CONSTEXPR
1514  tuple(allocator_arg_t __tag, const _Alloc& __a,
1515  const tuple<_U1, _U2>& __in)
1516  : _Inherited(__tag, __a,
1517  static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
1518  { }
1519 
1520  template<typename _Alloc, typename _U1, typename _U2,
1521  _ExplicitCtor<true, const _U1&, const _U2&> = false>
1522  explicit
1523  _GLIBCXX20_CONSTEXPR
1524  tuple(allocator_arg_t __tag, const _Alloc& __a,
1525  const tuple<_U1, _U2>& __in)
1526  : _Inherited(__tag, __a,
1527  static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
1528  { }
1529 
1530  template<typename _Alloc, typename _U1, typename _U2,
1531  _ImplicitCtor<true, _U1, _U2> = true>
1532  _GLIBCXX20_CONSTEXPR
1533  tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
1534  : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
1535  { }
1536 
1537  template<typename _Alloc, typename _U1, typename _U2,
1538  _ExplicitCtor<true, _U1, _U2> = false>
1539  explicit
1540  _GLIBCXX20_CONSTEXPR
1541  tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
1542  : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
1543  { }
1544 
1545 #if __cplusplus > 202002L
1546  template<typename _Alloc, typename _U1, typename _U2>
1547  requires __constructible<_U1&, _U2&>
1548  explicit(!__convertible<_U1&, _U2&>)
1549  constexpr
1550  tuple(allocator_arg_t __tag, const _Alloc& __a,
1551  tuple<_U1, _U2>& __in)
1552  : _Inherited(__tag, __a,
1553  static_cast<_Tuple_impl<0, _U1, _U2>&>(__in))
1554  { }
1555 
1556  template<typename _Alloc, typename _U1, typename _U2>
1557  requires __constructible<const _U1, const _U2>
1558  explicit(!__convertible<const _U1, const _U2>)
1559  constexpr
1560  tuple(allocator_arg_t __tag, const _Alloc& __a,
1561  const tuple<_U1, _U2>&& __in)
1562  : _Inherited(__tag, __a,
1563  static_cast<const _Tuple_impl<0, _U1, _U2>&&>(__in))
1564  { }
1565 #endif // C++23
1566 
1567  template<typename _Alloc, typename _U1, typename _U2,
1568  _ImplicitCtor<true, const _U1&, const _U2&> = true>
1569  _GLIBCXX20_CONSTEXPR
1570  tuple(allocator_arg_t __tag, const _Alloc& __a,
1571  const pair<_U1, _U2>& __in)
1572  : _Inherited(__tag, __a, __in.first, __in.second) { }
1573 
1574  template<typename _Alloc, typename _U1, typename _U2,
1575  _ExplicitCtor<true, const _U1&, const _U2&> = false>
1576  explicit
1577  _GLIBCXX20_CONSTEXPR
1578  tuple(allocator_arg_t __tag, const _Alloc& __a,
1579  const pair<_U1, _U2>& __in)
1580  : _Inherited(__tag, __a, __in.first, __in.second) { }
1581 
1582  template<typename _Alloc, typename _U1, typename _U2,
1583  _ImplicitCtor<true, _U1, _U2> = true>
1584  _GLIBCXX20_CONSTEXPR
1585  tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
1586  : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
1587  std::forward<_U2>(__in.second)) { }
1588 
1589  template<typename _Alloc, typename _U1, typename _U2,
1590  _ExplicitCtor<true, _U1, _U2> = false>
1591  explicit
1592  _GLIBCXX20_CONSTEXPR
1593  tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
1594  : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
1595  std::forward<_U2>(__in.second)) { }
1596 
1597 #if __cplusplus > 202002L
1598  template<typename _Alloc, typename _U1, typename _U2>
1599  requires __constructible<_U1&, _U2&>
1600  explicit(!__convertible<_U1&, _U2&>)
1601  constexpr
1602  tuple(allocator_arg_t __tag, const _Alloc& __a,
1603  pair<_U1, _U2>& __in)
1604  : _Inherited(__tag, __a, __in.first, __in.second) { }
1605 
1606  template<typename _Alloc, typename _U1, typename _U2>
1607  requires __constructible<const _U1, const _U2>
1608  explicit(!__convertible<const _U1, const _U2>)
1609  constexpr
1610  tuple(allocator_arg_t __tag, const _Alloc& __a, const pair<_U1, _U2>&& __in)
1611  : _Inherited(__tag, __a, std::forward<const _U1>(__in.first),
1612  std::forward<const _U2>(__in.second)) { }
1613 #endif // C++23
1614 
1615  // Tuple assignment.
1616 
1617  _GLIBCXX20_CONSTEXPR
1618  tuple&
1619  operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
1620  const tuple&,
1621  const __nonesuch&> __in)
1622  noexcept(__nothrow_assignable<const _T1&, const _T2&>())
1623  {
1624  this->_M_assign(__in);
1625  return *this;
1626  }
1627 
1628  _GLIBCXX20_CONSTEXPR
1629  tuple&
1630  operator=(__conditional_t<__assignable<_T1, _T2>(),
1631  tuple&&,
1632  __nonesuch&&> __in)
1633  noexcept(__nothrow_assignable<_T1, _T2>())
1634  {
1635  this->_M_assign(std::move(__in));
1636  return *this;
1637  }
1638 
1639  template<typename _U1, typename _U2>
1640  _GLIBCXX20_CONSTEXPR
1641  __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
1642  operator=(const tuple<_U1, _U2>& __in)
1643  noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1644  {
1645  this->_M_assign(__in);
1646  return *this;
1647  }
1648 
1649  template<typename _U1, typename _U2>
1650  _GLIBCXX20_CONSTEXPR
1651  __enable_if_t<__assignable<_U1, _U2>(), tuple&>
1652  operator=(tuple<_U1, _U2>&& __in)
1653  noexcept(__nothrow_assignable<_U1, _U2>())
1654  {
1655  this->_M_assign(std::move(__in));
1656  return *this;
1657  }
1658 
1659 #if __cplusplus > 202002L
1660  constexpr const tuple&
1661  operator=(const tuple& __in) const
1662  requires is_copy_assignable_v<const _T1> && is_copy_assignable_v<const _T2>
1663  {
1664  this->_M_assign(__in);
1665  return *this;
1666  }
1667 
1668  constexpr const tuple&
1669  operator=(tuple&& __in) const
1670  requires is_assignable_v<const _T1&, _T1> && is_assignable_v<const _T2, _T2>
1671  {
1672  this->_M_assign(std::move(__in));
1673  return *this;
1674  }
1675 
1676  template<typename _U1, typename _U2>
1677  constexpr const tuple&
1678  operator=(const tuple<_U1, _U2>& __in) const
1679  requires is_assignable_v<const _T1&, const _U1&>
1680  && is_assignable_v<const _T2&, const _U2&>
1681  {
1682  this->_M_assign(__in);
1683  return *this;
1684  }
1685 
1686  template<typename _U1, typename _U2>
1687  constexpr const tuple&
1688  operator=(tuple<_U1, _U2>&& __in) const
1689  requires is_assignable_v<const _T1&, _U1>
1690  && is_assignable_v<const _T2&, _U2>
1691  {
1692  this->_M_assign(std::move(__in));
1693  return *this;
1694  }
1695 #endif // C++23
1696 
1697  template<typename _U1, typename _U2>
1698  _GLIBCXX20_CONSTEXPR
1699  __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
1700  operator=(const pair<_U1, _U2>& __in)
1701  noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1702  {
1703  this->_M_head(*this) = __in.first;
1704  this->_M_tail(*this)._M_head(*this) = __in.second;
1705  return *this;
1706  }
1707 
1708  template<typename _U1, typename _U2>
1709  _GLIBCXX20_CONSTEXPR
1710  __enable_if_t<__assignable<_U1, _U2>(), tuple&>
1711  operator=(pair<_U1, _U2>&& __in)
1712  noexcept(__nothrow_assignable<_U1, _U2>())
1713  {
1714  this->_M_head(*this) = std::forward<_U1>(__in.first);
1715  this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
1716  return *this;
1717  }
1718 
1719 #if __cplusplus > 202002L
1720  template<typename _U1, typename _U2>
1721  constexpr const tuple&
1722  operator=(const pair<_U1, _U2>& __in) const
1723  requires is_assignable_v<const _T1&, const _U1&>
1724  && is_assignable_v<const _T2&, const _U2&>
1725  {
1726  this->_M_head(*this) = __in.first;
1727  this->_M_tail(*this)._M_head(*this) = __in.second;
1728  return *this;
1729  }
1730 
1731  template<typename _U1, typename _U2>
1732  constexpr const tuple&
1733  operator=(pair<_U1, _U2>&& __in) const
1734  requires is_assignable_v<const _T1&, _U1>
1735  && is_assignable_v<const _T2&, _U2>
1736  {
1737  this->_M_head(*this) = std::forward<_U1>(__in.first);
1738  this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
1739  return *this;
1740  }
1741 #endif // C++23
1742 
1743  _GLIBCXX20_CONSTEXPR
1744  void
1745  swap(tuple& __in)
1746  noexcept(__and_<__is_nothrow_swappable<_T1>,
1747  __is_nothrow_swappable<_T2>>::value)
1748  { _Inherited::_M_swap(__in); }
1749 
1750 #if __cplusplus > 202002L
1751  constexpr void
1752  swap(const tuple& __in) const
1753  noexcept(__and_v<__is_nothrow_swappable<const _T1>,
1754  __is_nothrow_swappable<const _T2>>)
1755  requires is_swappable_v<const _T1> && is_swappable_v<const _T2>
1756  { _Inherited::_M_swap(__in); }
1757 #endif // C++23
1758  };
1759 
1760 
1761  /// class tuple_size
1762  template<typename... _Elements>
1763  struct tuple_size<tuple<_Elements...>>
1764  : public integral_constant<size_t, sizeof...(_Elements)> { };
1765 
1766 #if __cplusplus >= 201703L
1767  template<typename... _Types>
1768  inline constexpr size_t tuple_size_v<tuple<_Types...>>
1769  = sizeof...(_Types);
1770 
1771  template<typename... _Types>
1772  inline constexpr size_t tuple_size_v<const tuple<_Types...>>
1773  = sizeof...(_Types);
1774 #endif
1775 
1776  /// Trait to get the Ith element type from a tuple.
1777  template<size_t __i, typename... _Types>
1778  struct tuple_element<__i, tuple<_Types...>>
1779  {
1780  static_assert(__i < sizeof...(_Types), "tuple index must be in range");
1781 
1782  using type = typename _Nth_type<__i, _Types...>::type;
1783  };
1784 
1785  template<size_t __i, typename _Head, typename... _Tail>
1786  constexpr _Head&
1787  __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
1788  { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
1789 
1790  template<size_t __i, typename _Head, typename... _Tail>
1791  constexpr const _Head&
1792  __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
1793  { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
1794 
1795  // Deleted overload to improve diagnostics for invalid indices
1796  template<size_t __i, typename... _Types>
1797  __enable_if_t<(__i >= sizeof...(_Types))>
1798  __get_helper(const tuple<_Types...>&) = delete;
1799 
1800  /// Return a reference to the ith element of a tuple.
1801  template<size_t __i, typename... _Elements>
1802  constexpr __tuple_element_t<__i, tuple<_Elements...>>&
1803  get(tuple<_Elements...>& __t) noexcept
1804  { return std::__get_helper<__i>(__t); }
1805 
1806  /// Return a const reference to the ith element of a const tuple.
1807  template<size_t __i, typename... _Elements>
1808  constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
1809  get(const tuple<_Elements...>& __t) noexcept
1810  { return std::__get_helper<__i>(__t); }
1811 
1812  /// Return an rvalue reference to the ith element of a tuple rvalue.
1813  template<size_t __i, typename... _Elements>
1814  constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
1815  get(tuple<_Elements...>&& __t) noexcept
1816  {
1817  typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
1818  return std::forward<__element_type>(std::__get_helper<__i>(__t));
1819  }
1820 
1821  /// Return a const rvalue reference to the ith element of a const tuple rvalue.
1822  template<size_t __i, typename... _Elements>
1823  constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
1824  get(const tuple<_Elements...>&& __t) noexcept
1825  {
1826  typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
1827  return std::forward<const __element_type>(std::__get_helper<__i>(__t));
1828  }
1829 
1830  /// @cond undocumented
1831  // Deleted overload chosen for invalid indices.
1832  template<size_t __i, typename... _Elements>
1833  constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
1834  get(const tuple<_Elements...>&) = delete;
1835  /// @endcond
1836 
1837 #if __cplusplus >= 201402L
1838 
1839 #define __cpp_lib_tuples_by_type 201304L
1840 
1841  /// Return a reference to the unique element of type _Tp of a tuple.
1842  template <typename _Tp, typename... _Types>
1843  constexpr _Tp&
1844  get(tuple<_Types...>& __t) noexcept
1845  {
1846  constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1847  static_assert(__idx < sizeof...(_Types),
1848  "the type T in std::get<T> must occur exactly once in the tuple");
1849  return std::__get_helper<__idx>(__t);
1850  }
1851 
1852  /// Return a reference to the unique element of type _Tp of a tuple rvalue.
1853  template <typename _Tp, typename... _Types>
1854  constexpr _Tp&&
1855  get(tuple<_Types...>&& __t) noexcept
1856  {
1857  constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1858  static_assert(__idx < sizeof...(_Types),
1859  "the type T in std::get<T> must occur exactly once in the tuple");
1860  return std::forward<_Tp>(std::__get_helper<__idx>(__t));
1861  }
1862 
1863  /// Return a const reference to the unique element of type _Tp of a tuple.
1864  template <typename _Tp, typename... _Types>
1865  constexpr const _Tp&
1866  get(const tuple<_Types...>& __t) noexcept
1867  {
1868  constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1869  static_assert(__idx < sizeof...(_Types),
1870  "the type T in std::get<T> must occur exactly once in the tuple");
1871  return std::__get_helper<__idx>(__t);
1872  }
1873 
1874  /// Return a const reference to the unique element of type _Tp of
1875  /// a const tuple rvalue.
1876  template <typename _Tp, typename... _Types>
1877  constexpr const _Tp&&
1878  get(const tuple<_Types...>&& __t) noexcept
1879  {
1880  constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1881  static_assert(__idx < sizeof...(_Types),
1882  "the type T in std::get<T> must occur exactly once in the tuple");
1883  return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
1884  }
1885 #endif
1886 
1887  // This class performs the comparison operations on tuples
1888  template<typename _Tp, typename _Up, size_t __i, size_t __size>
1889  struct __tuple_compare
1890  {
1891  static constexpr bool
1892  __eq(const _Tp& __t, const _Up& __u)
1893  {
1894  return bool(std::get<__i>(__t) == std::get<__i>(__u))
1895  && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
1896  }
1897 
1898  static constexpr bool
1899  __less(const _Tp& __t, const _Up& __u)
1900  {
1901  return bool(std::get<__i>(__t) < std::get<__i>(__u))
1902  || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
1903  && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
1904  }
1905  };
1906 
1907  template<typename _Tp, typename _Up, size_t __size>
1908  struct __tuple_compare<_Tp, _Up, __size, __size>
1909  {
1910  static constexpr bool
1911  __eq(const _Tp&, const _Up&) { return true; }
1912 
1913  static constexpr bool
1914  __less(const _Tp&, const _Up&) { return false; }
1915  };
1916 
1917  template<typename... _TElements, typename... _UElements>
1918  constexpr bool
1919  operator==(const tuple<_TElements...>& __t,
1920  const tuple<_UElements...>& __u)
1921  {
1922  static_assert(sizeof...(_TElements) == sizeof...(_UElements),
1923  "tuple objects can only be compared if they have equal sizes.");
1924  using __compare = __tuple_compare<tuple<_TElements...>,
1925  tuple<_UElements...>,
1926  0, sizeof...(_TElements)>;
1927  return __compare::__eq(__t, __u);
1928  }
1929 
1930 #if __cpp_lib_three_way_comparison
1931  template<typename _Cat, typename _Tp, typename _Up>
1932  constexpr _Cat
1933  __tuple_cmp(const _Tp&, const _Up&, index_sequence<>)
1934  { return _Cat::equivalent; }
1935 
1936  template<typename _Cat, typename _Tp, typename _Up,
1937  size_t _Idx0, size_t... _Idxs>
1938  constexpr _Cat
1939  __tuple_cmp(const _Tp& __t, const _Up& __u,
1940  index_sequence<_Idx0, _Idxs...>)
1941  {
1942  auto __c
1943  = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u));
1944  if (__c != 0)
1945  return __c;
1946  return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>());
1947  }
1948 
1949  template<typename... _Tps, typename... _Ups>
1950  constexpr
1951  common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
1952  operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
1953  {
1954  using _Cat
1955  = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
1956  return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
1957  }
1958 #else
1959  template<typename... _TElements, typename... _UElements>
1960  constexpr bool
1961  operator<(const tuple<_TElements...>& __t,
1962  const tuple<_UElements...>& __u)
1963  {
1964  static_assert(sizeof...(_TElements) == sizeof...(_UElements),
1965  "tuple objects can only be compared if they have equal sizes.");
1966  using __compare = __tuple_compare<tuple<_TElements...>,
1967  tuple<_UElements...>,
1968  0, sizeof...(_TElements)>;
1969  return __compare::__less(__t, __u);
1970  }
1971 
1972  template<typename... _TElements, typename... _UElements>
1973  constexpr bool
1974  operator!=(const tuple<_TElements...>& __t,
1975  const tuple<_UElements...>& __u)
1976  { return !(__t == __u); }
1977 
1978  template<typename... _TElements, typename... _UElements>
1979  constexpr bool
1980  operator>(const tuple<_TElements...>& __t,
1981  const tuple<_UElements...>& __u)
1982  { return __u < __t; }
1983 
1984  template<typename... _TElements, typename... _UElements>
1985  constexpr bool
1986  operator<=(const tuple<_TElements...>& __t,
1987  const tuple<_UElements...>& __u)
1988  { return !(__u < __t); }
1989 
1990  template<typename... _TElements, typename... _UElements>
1991  constexpr bool
1992  operator>=(const tuple<_TElements...>& __t,
1993  const tuple<_UElements...>& __u)
1994  { return !(__t < __u); }
1995 #endif // three_way_comparison
1996 
1997  // NB: DR 705.
1998  /// Create a tuple containing copies of the arguments
1999  template<typename... _Elements>
2000  constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
2001  make_tuple(_Elements&&... __args)
2002  {
2003  typedef tuple<typename __decay_and_strip<_Elements>::__type...>
2004  __result_type;
2005  return __result_type(std::forward<_Elements>(__args)...);
2006  }
2007 
2008  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2009  // 2275. Why is forward_as_tuple not constexpr?
2010  /// Create a tuple of lvalue or rvalue references to the arguments
2011  template<typename... _Elements>
2012  constexpr tuple<_Elements&&...>
2013  forward_as_tuple(_Elements&&... __args) noexcept
2014  { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2015 
2016  // Declarations of std::array and its std::get overloads, so that
2017  // std::tuple_cat can use them if <tuple> is included before <array>.
2018 
2019  template<typename _Tp, size_t _Nm> struct array;
2020 
2021  template<size_t _Int, typename _Tp, size_t _Nm>
2022  constexpr _Tp&
2023  get(array<_Tp, _Nm>&) noexcept;
2024 
2025  template<size_t _Int, typename _Tp, size_t _Nm>
2026  constexpr _Tp&&
2027  get(array<_Tp, _Nm>&&) noexcept;
2028 
2029  template<size_t _Int, typename _Tp, size_t _Nm>
2030  constexpr const _Tp&
2031  get(const array<_Tp, _Nm>&) noexcept;
2032 
2033  template<size_t _Int, typename _Tp, size_t _Nm>
2034  constexpr const _Tp&&
2035  get(const array<_Tp, _Nm>&&) noexcept;
2036 
2037  /// @cond undocumented
2038  template<size_t, typename, typename, size_t>
2039  struct __make_tuple_impl;
2040 
2041  template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
2042  struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
2043  : __make_tuple_impl<_Idx + 1,
2044  tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
2045  _Tuple, _Nm>
2046  { };
2047 
2048  template<size_t _Nm, typename _Tuple, typename... _Tp>
2049  struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
2050  {
2051  typedef tuple<_Tp...> __type;
2052  };
2053 
2054  template<typename _Tuple>
2055  struct __do_make_tuple
2056  : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
2057  { };
2058 
2059  // Returns the std::tuple equivalent of a tuple-like type.
2060  template<typename _Tuple>
2061  struct __make_tuple
2062  : public __do_make_tuple<__remove_cvref_t<_Tuple>>
2063  { };
2064 
2065  // Combines several std::tuple's into a single one.
2066  template<typename...>
2067  struct __combine_tuples;
2068 
2069  template<>
2070  struct __combine_tuples<>
2071  {
2072  typedef tuple<> __type;
2073  };
2074 
2075  template<typename... _Ts>
2076  struct __combine_tuples<tuple<_Ts...>>
2077  {
2078  typedef tuple<_Ts...> __type;
2079  };
2080 
2081  template<typename... _T1s, typename... _T2s, typename... _Rem>
2082  struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
2083  {
2084  typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
2085  _Rem...>::__type __type;
2086  };
2087 
2088  // Computes the result type of tuple_cat given a set of tuple-like types.
2089  template<typename... _Tpls>
2090  struct __tuple_cat_result
2091  {
2092  typedef typename __combine_tuples
2093  <typename __make_tuple<_Tpls>::__type...>::__type __type;
2094  };
2095 
2096  // Helper to determine the index set for the first tuple-like
2097  // type of a given set.
2098  template<typename...>
2099  struct __make_1st_indices;
2100 
2101  template<>
2102  struct __make_1st_indices<>
2103  {
2104  typedef _Index_tuple<> __type;
2105  };
2106 
2107  template<typename _Tp, typename... _Tpls>
2108  struct __make_1st_indices<_Tp, _Tpls...>
2109  {
2110  typedef typename _Build_index_tuple<tuple_size<
2111  typename remove_reference<_Tp>::type>::value>::__type __type;
2112  };
2113 
2114  // Performs the actual concatenation by step-wise expanding tuple-like
2115  // objects into the elements, which are finally forwarded into the
2116  // result tuple.
2117  template<typename _Ret, typename _Indices, typename... _Tpls>
2118  struct __tuple_concater;
2119 
2120  template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2121  struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2122  {
2123  template<typename... _Us>
2124  static constexpr _Ret
2125  _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2126  {
2127  typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2128  typedef __tuple_concater<_Ret, __idx, _Tpls...> __next;
2129  return __next::_S_do(std::forward<_Tpls>(__tps)...,
2130  std::forward<_Us>(__us)...,
2131  std::get<_Is>(std::forward<_Tp>(__tp))...);
2132  }
2133  };
2134 
2135  template<typename _Ret>
2136  struct __tuple_concater<_Ret, _Index_tuple<>>
2137  {
2138  template<typename... _Us>
2139  static constexpr _Ret
2140  _S_do(_Us&&... __us)
2141  {
2142  return _Ret(std::forward<_Us>(__us)...);
2143  }
2144  };
2145 
2146  template<typename... _Tps>
2147  struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2148  { };
2149  /// @endcond
2150 
2151  /// Create a `tuple` containing all elements from multiple tuple-like objects
2152  template<typename... _Tpls, typename = typename
2153  enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2154  constexpr auto
2155  tuple_cat(_Tpls&&... __tpls)
2156  -> typename __tuple_cat_result<_Tpls...>::__type
2157  {
2158  typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2159  typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2160  typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2161  return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2162  }
2163 
2164  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2165  // 2301. Why is tie not constexpr?
2166  /// Return a tuple of lvalue references bound to the arguments
2167  template<typename... _Elements>
2168  constexpr tuple<_Elements&...>
2169  tie(_Elements&... __args) noexcept
2170  { return tuple<_Elements&...>(__args...); }
2171 
2172  /// Exchange the values of two tuples
2173  template<typename... _Elements>
2174  _GLIBCXX20_CONSTEXPR
2175  inline
2176 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2177  // Constrained free swap overload, see p0185r1
2178  typename enable_if<__and_<__is_swappable<_Elements>...>::value
2179  >::type
2180 #else
2181  void
2182 #endif
2183  swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
2184  noexcept(noexcept(__x.swap(__y)))
2185  { __x.swap(__y); }
2186 
2187 #if __cplusplus > 202002L
2188  template<typename... _Elements>
2189  requires (is_swappable_v<const _Elements> && ...)
2190  constexpr void
2191  swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2192  noexcept(noexcept(__x.swap(__y)))
2193  { __x.swap(__y); }
2194 #endif // C++23
2195 
2196 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2197  /// Exchange the values of two const tuples (if const elements can be swapped)
2198  template<typename... _Elements>
2199  _GLIBCXX20_CONSTEXPR
2200  typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2201  swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2202 #endif
2203 
2204  // A class (and instance) which can be used in 'tie' when an element
2205  // of a tuple is not required.
2206  // _GLIBCXX14_CONSTEXPR
2207  // 2933. PR for LWG 2773 could be clearer
2208  struct _Swallow_assign
2209  {
2210  template<class _Tp>
2211  _GLIBCXX14_CONSTEXPR const _Swallow_assign&
2212  operator=(const _Tp&) const
2213  { return *this; }
2214  };
2215 
2216  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2217  // 2773. Making std::ignore constexpr
2218  /** Used with `std::tie` to ignore an element of a tuple
2219  *
2220  * When using `std::tie` to assign the elements of a tuple to variables,
2221  * unwanted elements can be ignored by using `std::ignore`. For example:
2222  *
2223  * ```
2224  * int x, y;
2225  * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3);
2226  * ```
2227  *
2228  * This assignment will perform `x=1; std::ignore=2; y=3;` which results
2229  * in the second element being ignored.
2230  *
2231  * @since C++11
2232  */
2233  _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{};
2234 
2235  /// Partial specialization for tuples
2236  template<typename... _Types, typename _Alloc>
2237  struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2238 
2239  // See stl_pair.h...
2240  /** "piecewise construction" using a tuple of arguments for each member.
2241  *
2242  * @param __first Arguments for the first member of the pair.
2243  * @param __second Arguments for the second member of the pair.
2244  *
2245  * The elements of each tuple will be used as the constructor arguments
2246  * for the data members of the pair.
2247  */
2248  template<class _T1, class _T2>
2249  template<typename... _Args1, typename... _Args2>
2250  _GLIBCXX20_CONSTEXPR
2251  inline
2252  pair<_T1, _T2>::
2253  pair(piecewise_construct_t,
2254  tuple<_Args1...> __first, tuple<_Args2...> __second)
2255  : pair(__first, __second,
2256  typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2257  typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2258  { }
2259 
2260  template<class _T1, class _T2>
2261  template<typename... _Args1, size_t... _Indexes1,
2262  typename... _Args2, size_t... _Indexes2>
2263  _GLIBCXX20_CONSTEXPR inline
2264  pair<_T1, _T2>::
2265  pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2266  _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2267  : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2268  second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2269  { }
2270 
2271 #if __cplusplus >= 201703L
2272 
2273  // Unpack a std::tuple into a type trait and use its value.
2274  // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2275  // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2276  // Otherwise the result is false (because we don't know if std::get throws).
2277  template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2278  inline constexpr bool __unpack_std_tuple = false;
2279 
2280  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2281  inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2282  = _Trait<_Tp, _Up...>::value;
2283 
2284  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2285  inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2286  = _Trait<_Tp, _Up&...>::value;
2287 
2288  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2289  inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2290  = _Trait<_Tp, const _Up...>::value;
2291 
2292  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2293  inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2294  = _Trait<_Tp, const _Up&...>::value;
2295 
2296 # define __cpp_lib_apply 201603L
2297 
2298  template <typename _Fn, typename _Tuple, size_t... _Idx>
2299  constexpr decltype(auto)
2300  __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2301  {
2302  return std::__invoke(std::forward<_Fn>(__f),
2303  std::get<_Idx>(std::forward<_Tuple>(__t))...);
2304  }
2305 
2306  template <typename _Fn, typename _Tuple>
2307  constexpr decltype(auto)
2308  apply(_Fn&& __f, _Tuple&& __t)
2309  noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2310  {
2311  using _Indices
2312  = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2313  return std::__apply_impl(std::forward<_Fn>(__f),
2314  std::forward<_Tuple>(__t),
2315  _Indices{});
2316  }
2317 
2318 #define __cpp_lib_make_from_tuple 201606L
2319 
2320  template <typename _Tp, typename _Tuple, size_t... _Idx>
2321  constexpr _Tp
2322  __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
2323  { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
2324 
2325  template <typename _Tp, typename _Tuple>
2326  constexpr _Tp
2327  make_from_tuple(_Tuple&& __t)
2328  noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
2329  {
2330  constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
2331 #if __has_builtin(__reference_constructs_from_temporary)
2332  if constexpr (__n == 1)
2333  {
2334  using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
2335  static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
2336  }
2337 #endif
2338  return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
2339  make_index_sequence<__n>{});
2340  }
2341 #endif // C++17
2342 
2343 #if __cplusplus > 202002L
2344  template<typename... _TTypes, typename... _UTypes,
2345  template<typename> class _TQual, template<typename> class _UQual>
2346  requires requires { typename tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; }
2347  struct basic_common_reference<tuple<_TTypes...>, tuple<_UTypes...>, _TQual, _UQual>
2348  { using type = tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; };
2349 
2350  template<typename... _TTypes, typename... _UTypes>
2351  requires requires { typename tuple<common_type_t<_TTypes, _UTypes>...>; }
2352  struct common_type<tuple<_TTypes...>, tuple<_UTypes...>>
2353  { using type = tuple<common_type_t<_TTypes, _UTypes>...>; };
2354 #endif // C++23
2355 
2356  /// @}
2357 
2358 _GLIBCXX_END_NAMESPACE_VERSION
2359 } // namespace std
2360 
2361 #endif // C++11
2362 
2363 #endif // _GLIBCXX_TUPLE