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