libstdc++
tuple
Go to the documentation of this file.
1 // <tuple> -*- C++ -*-
2 
3 // Copyright (C) 2007-2026 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 type_identity_t<_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 type_identity_t<_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 __type_identity_t<_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 __type_identity_t<_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 __type_identity_t<_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 __type_identity_t<_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,
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>
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  // We need the default since we're going to define no-op
1988  // allocator constructors.
1989  tuple() = default;
1990  // Defaulted copy operations to maintain trivial copyability.
1991  // and support non-const assignment expressions.
1992  tuple(const tuple&) = default;
1993  tuple& operator=(const tuple&) = default;
1994 
1995  _GLIBCXX20_CONSTEXPR
1996  void swap(tuple&) noexcept { /* no-op */ }
1997 
1998 #if __cpp_lib_ranges_zip // >= C++23
1999  template<same_as<tuple> _Tuple = tuple>
2000  constexpr const tuple&
2001  operator=(const _Tuple&) const noexcept
2002  { return *this; }
2003 
2004  constexpr void swap(const tuple&) const noexcept
2005  { /* no-op */ }
2006 #endif
2007 
2008  // No-op allocator constructors.
2009  template<typename _Alloc>
2010  _GLIBCXX20_CONSTEXPR
2011  tuple(allocator_arg_t, const _Alloc&) noexcept { }
2012  template<typename _Alloc>
2013  _GLIBCXX20_CONSTEXPR
2014  tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
2015 
2016 #if __cpp_lib_tuple_like // >= C++23
2017  template<__tuple_like _UTuple>
2018  requires (!is_same_v<remove_cvref_t<_UTuple>, tuple>)
2019  && (!is_same_v<remove_cvref_t<_UTuple>, allocator_arg_t>)
2020  && (tuple_size_v<remove_cvref_t<_UTuple>> == 0)
2021  constexpr
2022  tuple(_UTuple&&) noexcept { }
2023 
2024  template<typename _Alloc, __tuple_like _UTuple>
2025  requires (!is_same_v<remove_cvref_t<_UTuple>, tuple>)
2026  && (tuple_size_v<remove_cvref_t<_UTuple>> == 0)
2027  constexpr
2028  tuple(allocator_arg_t, const _Alloc&, _UTuple&&) noexcept { }
2029 
2030  template<__tuple_like _UTuple>
2031  requires (!is_same_v<remove_cvref_t<_UTuple>, tuple>)
2032  && (tuple_size_v<remove_cvref_t<_UTuple>> == 0)
2033  constexpr tuple&
2034  operator=(_UTuple&&) noexcept
2035  { return *this; }
2036 
2037  template<__tuple_like _UTuple>
2038  requires (!is_same_v<remove_cvref_t<_UTuple>, tuple>)
2039  && (tuple_size_v<remove_cvref_t<_UTuple>> == 0)
2040  constexpr const tuple&
2041  operator=(_UTuple&&) const noexcept
2042  { return *this; }
2043 
2044  template<__tuple_like _UTuple>
2045  requires (!__is_tuple_v<_UTuple>) && (tuple_size_v<_UTuple> == 0)
2046  [[nodiscard]]
2047  friend constexpr bool
2048  operator==(const tuple&, const _UTuple&) noexcept
2049  { return true; }
2050 
2051  template<__tuple_like _UTuple>
2052  requires (!__is_tuple_v<_UTuple>) && (tuple_size_v<_UTuple> == 0)
2053  friend constexpr strong_ordering
2054  operator<=>(const tuple&, const _UTuple&) noexcept
2055  { return strong_ordering::equal; }
2056 #endif // C++23
2057  };
2058 
2059 #if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20
2060  /// Partial specialization, 2-element tuple.
2061  /// Includes construction and assignment from a pair.
2062  template<typename _T1, typename _T2>
2063  class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
2064  {
2065  typedef _Tuple_impl<0, _T1, _T2> _Inherited;
2066 
2067  // Constraint for non-explicit default constructor
2068  template<bool _Dummy, typename _U1, typename _U2>
2069  using _ImplicitDefaultCtor = __enable_if_t<
2070  _TupleConstraints<_Dummy, _U1, _U2>::
2071  __is_implicitly_default_constructible(),
2072  bool>;
2073 
2074  // Constraint for explicit default constructor
2075  template<bool _Dummy, typename _U1, typename _U2>
2076  using _ExplicitDefaultCtor = __enable_if_t<
2077  _TupleConstraints<_Dummy, _U1, _U2>::
2078  __is_explicitly_default_constructible(),
2079  bool>;
2080 
2081  template<bool _Dummy>
2082  using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
2083 
2084  // Constraint for non-explicit constructors
2085  template<bool _Cond, typename _U1, typename _U2>
2086  using _ImplicitCtor = __enable_if_t<
2087  _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
2088  bool>;
2089 
2090  // Constraint for non-explicit constructors
2091  template<bool _Cond, typename _U1, typename _U2>
2092  using _ExplicitCtor = __enable_if_t<
2093  _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
2094  bool>;
2095 
2096  template<typename _U1, typename _U2>
2097  static constexpr bool __assignable()
2098  {
2099  return __and_<is_assignable<_T1&, _U1>,
2100  is_assignable<_T2&, _U2>>::value;
2101  }
2102 
2103  template<typename _U1, typename _U2>
2104  static constexpr bool __nothrow_assignable()
2105  {
2106  return __and_<is_nothrow_assignable<_T1&, _U1>,
2108  }
2109 
2110  template<typename _U1, typename _U2>
2111  static constexpr bool __nothrow_constructible()
2112  {
2113  return __and_<is_nothrow_constructible<_T1, _U1>,
2115  }
2116 
2117  static constexpr bool __nothrow_default_constructible()
2118  {
2119  return __and_<is_nothrow_default_constructible<_T1>,
2121  }
2122 
2123  template<typename _U1>
2124  static constexpr bool __is_alloc_arg()
2125  { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
2126 
2127  /// @cond undocumented
2128 #undef __glibcxx_no_dangling_refs
2129  // Error if construction from _U1 and _U2 would create a dangling ref.
2130 #if __has_builtin(__reference_constructs_from_temporary) \
2131  && defined _GLIBCXX_DEBUG
2132 # define __glibcxx_no_dangling_refs(_U1, _U2) \
2133  static_assert(!__reference_constructs_from_temporary(_T1, _U1) \
2134  && !__reference_constructs_from_temporary(_T2, _U2), \
2135  "std::tuple constructor creates a dangling reference")
2136 #else
2137 # define __glibcxx_no_dangling_refs(_U1, _U2)
2138 #endif
2139  /// @endcond
2140 
2141  public:
2142  template<bool _Dummy = true,
2143  _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
2144  constexpr
2145  tuple()
2146  noexcept(__nothrow_default_constructible())
2147  : _Inherited() { }
2148 
2149  template<bool _Dummy = true,
2150  _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
2151  explicit constexpr
2152  tuple()
2153  noexcept(__nothrow_default_constructible())
2154  : _Inherited() { }
2155 
2156  template<bool _Dummy = true,
2157  _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2158  constexpr
2159  tuple(const _T1& __a1, const _T2& __a2)
2160  noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2161  : _Inherited(__a1, __a2) { }
2162 
2163  template<bool _Dummy = true,
2164  _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2165  explicit constexpr
2166  tuple(const _T1& __a1, const _T2& __a2)
2167  noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2168  : _Inherited(__a1, __a2) { }
2169 
2170  template<typename _U1, typename _U2,
2171  _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
2172  constexpr
2173  tuple(_U1&& __a1, _U2&& __a2)
2174  noexcept(__nothrow_constructible<_U1, _U2>())
2175  : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2176  { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2177 
2178  template<typename _U1, typename _U2,
2179  _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
2180  explicit constexpr
2181  tuple(_U1&& __a1, _U2&& __a2)
2182  noexcept(__nothrow_constructible<_U1, _U2>())
2183  : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2184  { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2185 
2186  constexpr tuple(const tuple&) = default;
2187 
2188  constexpr tuple(tuple&&) = default;
2189 
2190  template<typename _U1, typename _U2,
2191  _ImplicitCtor<true, const _U1&, const _U2&> = true>
2192  constexpr
2193  tuple(const tuple<_U1, _U2>& __in)
2194  noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2195  : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2196  { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2197 
2198  template<typename _U1, typename _U2,
2199  _ExplicitCtor<true, const _U1&, const _U2&> = false>
2200  explicit constexpr
2201  tuple(const tuple<_U1, _U2>& __in)
2202  noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2203  : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2204  { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2205 
2206  template<typename _U1, typename _U2,
2207  _ImplicitCtor<true, _U1, _U2> = true>
2208  constexpr
2209  tuple(tuple<_U1, _U2>&& __in)
2210  noexcept(__nothrow_constructible<_U1, _U2>())
2211  : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2212  { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2213 
2214  template<typename _U1, typename _U2,
2215  _ExplicitCtor<true, _U1, _U2> = false>
2216  explicit constexpr
2217  tuple(tuple<_U1, _U2>&& __in)
2218  noexcept(__nothrow_constructible<_U1, _U2>())
2219  : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2220  { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2221 
2222  template<typename _U1, typename _U2,
2223  _ImplicitCtor<true, const _U1&, const _U2&> = true>
2224  constexpr
2225  tuple(const pair<_U1, _U2>& __in)
2226  noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2227  : _Inherited(__in.first, __in.second)
2228  { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2229 
2230  template<typename _U1, typename _U2,
2231  _ExplicitCtor<true, const _U1&, const _U2&> = false>
2232  explicit constexpr
2233  tuple(const pair<_U1, _U2>& __in)
2234  noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2235  : _Inherited(__in.first, __in.second)
2236  { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2237 
2238  template<typename _U1, typename _U2,
2239  _ImplicitCtor<true, _U1, _U2> = true>
2240  constexpr
2241  tuple(pair<_U1, _U2>&& __in)
2242  noexcept(__nothrow_constructible<_U1, _U2>())
2243  : _Inherited(std::forward<_U1>(__in.first),
2244  std::forward<_U2>(__in.second))
2245  { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2246 
2247  template<typename _U1, typename _U2,
2248  _ExplicitCtor<true, _U1, _U2> = false>
2249  explicit constexpr
2250  tuple(pair<_U1, _U2>&& __in)
2251  noexcept(__nothrow_constructible<_U1, _U2>())
2252  : _Inherited(std::forward<_U1>(__in.first),
2253  std::forward<_U2>(__in.second))
2254  { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2255 
2256  // Allocator-extended constructors.
2257 
2258  template<typename _Alloc,
2259  _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
2260  _GLIBCXX20_CONSTEXPR
2261  tuple(allocator_arg_t __tag, const _Alloc& __a)
2262  : _Inherited(__tag, __a) { }
2263 
2264  template<typename _Alloc,
2265  _ExplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = false>
2266  _GLIBCXX20_CONSTEXPR
2267  explicit
2268  tuple(allocator_arg_t __tag, const _Alloc& __a)
2269  : _Inherited(__tag, __a) { }
2270 
2271  template<typename _Alloc, bool _Dummy = true,
2272  _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2273  _GLIBCXX20_CONSTEXPR
2274  tuple(allocator_arg_t __tag, const _Alloc& __a,
2275  const _T1& __a1, const _T2& __a2)
2276  : _Inherited(__tag, __a, __a1, __a2) { }
2277 
2278  template<typename _Alloc, bool _Dummy = true,
2279  _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2280  explicit
2281  _GLIBCXX20_CONSTEXPR
2282  tuple(allocator_arg_t __tag, const _Alloc& __a,
2283  const _T1& __a1, const _T2& __a2)
2284  : _Inherited(__tag, __a, __a1, __a2) { }
2285 
2286  template<typename _Alloc, typename _U1, typename _U2,
2287  _ImplicitCtor<true, _U1, _U2> = true>
2288  _GLIBCXX20_CONSTEXPR
2289  tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
2290  : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2291  std::forward<_U2>(__a2))
2292  { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2293 
2294  template<typename _Alloc, typename _U1, typename _U2,
2295  _ExplicitCtor<true, _U1, _U2> = false>
2296  explicit
2297  _GLIBCXX20_CONSTEXPR
2298  tuple(allocator_arg_t __tag, const _Alloc& __a,
2299  _U1&& __a1, _U2&& __a2)
2300  : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2301  std::forward<_U2>(__a2))
2302  { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2303 
2304  template<typename _Alloc>
2305  _GLIBCXX20_CONSTEXPR
2306  tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
2307  : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
2308 
2309  template<typename _Alloc>
2310  _GLIBCXX20_CONSTEXPR
2311  tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
2312  : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
2313 
2314  template<typename _Alloc, typename _U1, typename _U2,
2315  _ImplicitCtor<true, const _U1&, const _U2&> = true>
2316  _GLIBCXX20_CONSTEXPR
2317  tuple(allocator_arg_t __tag, const _Alloc& __a,
2318  const tuple<_U1, _U2>& __in)
2319  : _Inherited(__tag, __a,
2320  static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2321  { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2322 
2323  template<typename _Alloc, typename _U1, typename _U2,
2324  _ExplicitCtor<true, const _U1&, const _U2&> = false>
2325  explicit
2326  _GLIBCXX20_CONSTEXPR
2327  tuple(allocator_arg_t __tag, const _Alloc& __a,
2328  const tuple<_U1, _U2>& __in)
2329  : _Inherited(__tag, __a,
2330  static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2331  { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2332 
2333  template<typename _Alloc, typename _U1, typename _U2,
2334  _ImplicitCtor<true, _U1, _U2> = true>
2335  _GLIBCXX20_CONSTEXPR
2336  tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2337  : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2338  { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2339 
2340  template<typename _Alloc, typename _U1, typename _U2,
2341  _ExplicitCtor<true, _U1, _U2> = false>
2342  explicit
2343  _GLIBCXX20_CONSTEXPR
2344  tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2345  : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2346  { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2347 
2348  template<typename _Alloc, typename _U1, typename _U2,
2349  _ImplicitCtor<true, const _U1&, const _U2&> = true>
2350  _GLIBCXX20_CONSTEXPR
2351  tuple(allocator_arg_t __tag, const _Alloc& __a,
2352  const pair<_U1, _U2>& __in)
2353  : _Inherited(__tag, __a, __in.first, __in.second)
2354  { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2355 
2356  template<typename _Alloc, typename _U1, typename _U2,
2357  _ExplicitCtor<true, const _U1&, const _U2&> = false>
2358  explicit
2359  _GLIBCXX20_CONSTEXPR
2360  tuple(allocator_arg_t __tag, const _Alloc& __a,
2361  const pair<_U1, _U2>& __in)
2362  : _Inherited(__tag, __a, __in.first, __in.second)
2363  { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2364 
2365  template<typename _Alloc, typename _U1, typename _U2,
2366  _ImplicitCtor<true, _U1, _U2> = true>
2367  _GLIBCXX20_CONSTEXPR
2368  tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2369  : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2370  std::forward<_U2>(__in.second))
2371  { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2372 
2373  template<typename _Alloc, typename _U1, typename _U2,
2374  _ExplicitCtor<true, _U1, _U2> = false>
2375  explicit
2376  _GLIBCXX20_CONSTEXPR
2377  tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2378  : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2379  std::forward<_U2>(__in.second))
2380  { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2381 
2382  // Tuple assignment.
2383 
2384  _GLIBCXX20_CONSTEXPR
2385  tuple&
2386  operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
2387  const tuple&,
2388  const __nonesuch&> __in)
2389  noexcept(__nothrow_assignable<const _T1&, const _T2&>())
2390  {
2391  this->_M_assign(__in);
2392  return *this;
2393  }
2394 
2395  _GLIBCXX20_CONSTEXPR
2396  tuple&
2397  operator=(__conditional_t<__assignable<_T1, _T2>(),
2398  tuple&&,
2399  __nonesuch&&> __in)
2400  noexcept(__nothrow_assignable<_T1, _T2>())
2401  {
2402  this->_M_assign(std::move(__in));
2403  return *this;
2404  }
2405 
2406  template<typename _U1, typename _U2>
2407  _GLIBCXX20_CONSTEXPR
2408  __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2409  operator=(const tuple<_U1, _U2>& __in)
2410  noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2411  {
2412  this->_M_assign(__in);
2413  return *this;
2414  }
2415 
2416  template<typename _U1, typename _U2>
2417  _GLIBCXX20_CONSTEXPR
2418  __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2419  operator=(tuple<_U1, _U2>&& __in)
2420  noexcept(__nothrow_assignable<_U1, _U2>())
2421  {
2422  this->_M_assign(std::move(__in));
2423  return *this;
2424  }
2425 
2426  template<typename _U1, typename _U2>
2427  _GLIBCXX20_CONSTEXPR
2428  __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2429  operator=(const pair<_U1, _U2>& __in)
2430  noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2431  {
2432  this->_M_head(*this) = __in.first;
2433  this->_M_tail(*this)._M_head(*this) = __in.second;
2434  return *this;
2435  }
2436 
2437  template<typename _U1, typename _U2>
2438  _GLIBCXX20_CONSTEXPR
2439  __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2440  operator=(pair<_U1, _U2>&& __in)
2441  noexcept(__nothrow_assignable<_U1, _U2>())
2442  {
2443  this->_M_head(*this) = std::forward<_U1>(__in.first);
2444  this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
2445  return *this;
2446  }
2447 
2448  _GLIBCXX20_CONSTEXPR
2449  void
2450  swap(tuple& __in)
2451  noexcept(__and_<__is_nothrow_swappable<_T1>,
2452  __is_nothrow_swappable<_T2>>::value)
2453  { _Inherited::_M_swap(__in); }
2454  };
2455 #endif // concepts && conditional_explicit
2456 
2457  /// class tuple_size
2458  template<typename... _Elements>
2459  struct tuple_size<tuple<_Elements...>>
2460  : public integral_constant<size_t, sizeof...(_Elements)> { };
2461 
2462 #if __cplusplus >= 201703L
2463  template<typename... _Types>
2464  inline constexpr size_t tuple_size_v<tuple<_Types...>>
2465  = sizeof...(_Types);
2466 
2467  template<typename... _Types>
2468  inline constexpr size_t tuple_size_v<const tuple<_Types...>>
2469  = sizeof...(_Types);
2470 #endif
2471 
2472  /// Trait to get the Ith element type from a tuple.
2473  template<size_t __i, typename... _Types>
2474  struct tuple_element<__i, tuple<_Types...>>
2475  {
2476  static_assert(__i < sizeof...(_Types), "tuple index must be in range");
2477 
2478  using type = typename _Nth_type<__i, _Types...>::type;
2479  };
2480 
2481  template<size_t __i, typename _Head, typename... _Tail>
2482  constexpr _Head&
2483  __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2484  { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2485 
2486  template<size_t __i, typename _Head, typename... _Tail>
2487  constexpr const _Head&
2488  __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2489  { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2490 
2491  // Deleted overload to improve diagnostics for invalid indices
2492  template<size_t __i, typename... _Types>
2493  __enable_if_t<(__i >= sizeof...(_Types))>
2494  __get_helper(const tuple<_Types...>&) = delete;
2495 
2496  /// Return a reference to the ith element of a tuple.
2497  template<size_t __i, typename... _Elements>
2498  constexpr __tuple_element_t<__i, tuple<_Elements...>>&
2499  get(tuple<_Elements...>& __t) noexcept
2500  { return std::__get_helper<__i>(__t); }
2501 
2502  /// Return a const reference to the ith element of a const tuple.
2503  template<size_t __i, typename... _Elements>
2504  constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
2505  get(const tuple<_Elements...>& __t) noexcept
2506  { return std::__get_helper<__i>(__t); }
2507 
2508  /// Return an rvalue reference to the ith element of a tuple rvalue.
2509  template<size_t __i, typename... _Elements>
2510  constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
2511  get(tuple<_Elements...>&& __t) noexcept
2512  {
2513  typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2514  return std::forward<__element_type>(std::__get_helper<__i>(__t));
2515  }
2516 
2517  /// Return a const rvalue reference to the ith element of a const tuple rvalue.
2518  template<size_t __i, typename... _Elements>
2519  constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
2520  get(const tuple<_Elements...>&& __t) noexcept
2521  {
2522  typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2523  return std::forward<const __element_type>(std::__get_helper<__i>(__t));
2524  }
2525 
2526  /// @cond undocumented
2527  // Deleted overload chosen for invalid indices.
2528  template<size_t __i, typename... _Elements>
2529  constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
2530  get(const tuple<_Elements...>&) = delete;
2531  /// @endcond
2532 
2533 #ifdef __cpp_lib_tuples_by_type // C++ >= 14
2534  /// Return a reference to the unique element of type _Tp of a tuple.
2535  template <typename _Tp, typename... _Types>
2536  constexpr _Tp&
2537  get(tuple<_Types...>& __t) noexcept
2538  {
2539  constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2540  static_assert(__idx < sizeof...(_Types),
2541  "the type T in std::get<T> must occur exactly once in the tuple");
2542  return std::__get_helper<__idx>(__t);
2543  }
2544 
2545  /// Return a reference to the unique element of type _Tp of a tuple rvalue.
2546  template <typename _Tp, typename... _Types>
2547  constexpr _Tp&&
2548  get(tuple<_Types...>&& __t) noexcept
2549  {
2550  constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2551  static_assert(__idx < sizeof...(_Types),
2552  "the type T in std::get<T> must occur exactly once in the tuple");
2553  return std::forward<_Tp>(std::__get_helper<__idx>(__t));
2554  }
2555 
2556  /// Return a const reference to the unique element of type _Tp of a tuple.
2557  template <typename _Tp, typename... _Types>
2558  constexpr const _Tp&
2559  get(const tuple<_Types...>& __t) noexcept
2560  {
2561  constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2562  static_assert(__idx < sizeof...(_Types),
2563  "the type T in std::get<T> must occur exactly once in the tuple");
2564  return std::__get_helper<__idx>(__t);
2565  }
2566 
2567  /// Return a const reference to the unique element of type _Tp of
2568  /// a const tuple rvalue.
2569  template <typename _Tp, typename... _Types>
2570  constexpr const _Tp&&
2571  get(const tuple<_Types...>&& __t) noexcept
2572  {
2573  constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2574  static_assert(__idx < sizeof...(_Types),
2575  "the type T in std::get<T> must occur exactly once in the tuple");
2576  return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
2577  }
2578 #endif
2579 
2580 #if __cpp_lib_three_way_comparison
2581  template<typename... _Tps, typename... _Ups>
2582  requires (sizeof...(_Tps) == sizeof...(_Ups))
2583  && (requires (const _Tps& __t, const _Ups& __u) {
2584  { __t == __u } -> __detail::__boolean_testable;
2585  } && ...)
2586  constexpr bool
2587  operator== [[nodiscard]] (const tuple<_Tps...>& __t,
2588  const tuple<_Ups...>& __u)
2589  {
2590  return [&]<size_t... _Inds>(index_sequence<_Inds...>) {
2591  // Fold == over the tuples until non-equal elements are found.
2592  return (bool(std::get<_Inds>(__t) == std::get<_Inds>(__u)) && ...);
2593  }(index_sequence_for<_Tps...>{});
2594  }
2595 
2596  template<typename _Cat, typename _Tp, typename _Up, typename _IndexSeq>
2597  [[nodiscard]]
2598  constexpr _Cat
2599  __tuple_cmp(const _Tp& __t, const _Up& __u, _IndexSeq __indices)
2600  {
2601  _Cat __c = _Cat::equivalent;
2602 
2603  // Set __c to the comparison result of two corresponding elements.
2604  // Return true they are equivalent.
2605  auto __cmp = [&]<size_t _Ind>(integral_constant<size_t, _Ind>) {
2606  __c = __detail::__synth3way(std::get<_Ind>(__t), std::get<_Ind>(__u));
2607  return __c == 0;
2608  };
2609 
2610  [&]<size_t... _Inds>(index_sequence<_Inds...>) {
2611  // Fold __cmp over the tuples until non-equivalent elements are found.
2612  (void)(__cmp(integral_constant<size_t, _Inds>{}) && ...);
2613  }(__indices);
2614 
2615  return __c;
2616  }
2617 
2618  template<typename... _Tps, typename... _Ups>
2619  requires (sizeof...(_Tps) == sizeof...(_Ups))
2620  && (requires { typename __detail::__synth3way_t<_Tps, _Ups>; } && ...)
2621  constexpr
2622  common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
2623  operator<=> [[nodiscard]] (const tuple<_Tps...>& __t,
2624  const tuple<_Ups...>& __u)
2625  {
2626  using _Cat
2627  = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
2628  return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
2629  }
2630 #else
2631 
2632  // This class performs the comparison operations on tuples
2633  template<typename _Tp, typename _Up, size_t __i, size_t __size>
2634  struct __tuple_compare
2635  {
2636  static constexpr bool
2637  __eq(const _Tp& __t, const _Up& __u)
2638  {
2639  return bool(std::get<__i>(__t) == std::get<__i>(__u))
2640  && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
2641  }
2642 
2643  static constexpr bool
2644  __less(const _Tp& __t, const _Up& __u)
2645  {
2646  return bool(std::get<__i>(__t) < std::get<__i>(__u))
2647  || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
2648  && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
2649  }
2650  };
2651 
2652  template<typename _Tp, typename _Up, size_t __size>
2653  struct __tuple_compare<_Tp, _Up, __size, __size>
2654  {
2655  static constexpr bool
2656  __eq(const _Tp&, const _Up&) { return true; }
2657 
2658  static constexpr bool
2659  __less(const _Tp&, const _Up&) { return false; }
2660  };
2661 
2662  template<typename... _TElements, typename... _UElements>
2663  _GLIBCXX_NODISCARD
2664  constexpr bool
2665  operator==(const tuple<_TElements...>& __t,
2666  const tuple<_UElements...>& __u)
2667  {
2668  static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2669  "tuple objects can only be compared if they have equal sizes.");
2670  using __compare = __tuple_compare<tuple<_TElements...>,
2671  tuple<_UElements...>,
2672  0, sizeof...(_TElements)>;
2673  return __compare::__eq(__t, __u);
2674  }
2675 
2676  template<typename... _TElements, typename... _UElements>
2677  _GLIBCXX_NODISCARD
2678  constexpr bool
2679  operator<(const tuple<_TElements...>& __t,
2680  const tuple<_UElements...>& __u)
2681  {
2682  static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2683  "tuple objects can only be compared if they have equal sizes.");
2684  using __compare = __tuple_compare<tuple<_TElements...>,
2685  tuple<_UElements...>,
2686  0, sizeof...(_TElements)>;
2687  return __compare::__less(__t, __u);
2688  }
2689 
2690  template<typename... _TElements, typename... _UElements>
2691  _GLIBCXX_NODISCARD
2692  constexpr bool
2693  operator!=(const tuple<_TElements...>& __t,
2694  const tuple<_UElements...>& __u)
2695  { return !(__t == __u); }
2696 
2697  template<typename... _TElements, typename... _UElements>
2698  _GLIBCXX_NODISCARD
2699  constexpr bool
2700  operator>(const tuple<_TElements...>& __t,
2701  const tuple<_UElements...>& __u)
2702  { return __u < __t; }
2703 
2704  template<typename... _TElements, typename... _UElements>
2705  _GLIBCXX_NODISCARD
2706  constexpr bool
2707  operator<=(const tuple<_TElements...>& __t,
2708  const tuple<_UElements...>& __u)
2709  { return !(__u < __t); }
2710 
2711  template<typename... _TElements, typename... _UElements>
2712  _GLIBCXX_NODISCARD
2713  constexpr bool
2714  operator>=(const tuple<_TElements...>& __t,
2715  const tuple<_UElements...>& __u)
2716  { return !(__t < __u); }
2717 #endif // three_way_comparison
2718 
2719  // NB: DR 705.
2720  /// Create a tuple containing copies of the arguments
2721  template<typename... _Elements>
2723  make_tuple(_Elements&&... __args)
2724  {
2726  __result_type;
2727  return __result_type(std::forward<_Elements>(__args)...);
2728  }
2729 
2730  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2731  // 2275. Why is forward_as_tuple not constexpr?
2732  /// Create a tuple of lvalue or rvalue references to the arguments
2733  template<typename... _Elements>
2734  constexpr tuple<_Elements&&...>
2735  forward_as_tuple(_Elements&&... __args) noexcept
2736  { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2737 
2738  /// @cond undocumented
2739  template<typename _Tuple, typename _Idx_tuple>
2740  struct __do_make_tuple;
2741 
2742  template<typename _Tuple, size_t... _Idx>
2743  struct __do_make_tuple<_Tuple, _Index_tuple<_Idx...>>
2744  {
2745  using __type = tuple<__tuple_element_t<_Idx, _Tuple>...>;
2746  };
2747 
2748  // Returns the std::tuple equivalent of a tuple-like type.
2749  template<typename _Tuple,
2750  typename _Tup = __remove_cvref_t<_Tuple>,
2751  typename _Indices = _Build_index_tuple<tuple_size<_Tup>::value>>
2752  struct __make_tuple
2753  : __do_make_tuple<_Tup, typename _Indices::__type>
2754  { };
2755 
2756  // Combines several std::tuple types into a single one.
2757  template<typename...>
2758  struct __combine_tuples;
2759 
2760  template<>
2761  struct __combine_tuples<>
2762  {
2763  using __type = tuple<>;
2764  };
2765 
2766  template<typename... _Ts>
2767  struct __combine_tuples<tuple<_Ts...>>
2768  {
2769  using __type = tuple<_Ts...>;
2770  };
2771 
2772  template<typename... _T1s, typename... _T2s>
2773  struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>>
2774  {
2775  using __type = tuple<_T1s..., _T2s...>;
2776  };
2777 
2778  template<typename... _T1s, typename... _T2s, typename... _T3s,
2779  typename... _Rem>
2780  struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, tuple<_T3s...>,
2781  _Rem...>
2782  {
2783  using _First = tuple<_T1s..., _T2s..., _T3s...>;
2784  using _Second = typename __combine_tuples<_Rem...>::__type;
2785  using __type = typename __combine_tuples<_First, _Second>::__type;
2786  };
2787 
2788  // Computes the result type of tuple_cat given a set of tuple-like types.
2789  template<typename... _Tpls>
2790  struct __tuple_cat_result
2791  {
2792  typedef typename __combine_tuples
2793  <typename __make_tuple<_Tpls>::__type...>::__type __type;
2794  };
2795 
2796  // Helper to determine the index set for the first tuple-like
2797  // type of a given set.
2798  template<typename...>
2799  struct __make_1st_indices;
2800 
2801  template<>
2802  struct __make_1st_indices<>
2803  {
2804  typedef _Index_tuple<> __type;
2805  };
2806 
2807  template<typename _Tp, typename... _Tpls>
2808  struct __make_1st_indices<_Tp, _Tpls...>
2809  {
2810  typedef typename _Build_index_tuple<tuple_size<
2811  typename remove_reference<_Tp>::type>::value>::__type __type;
2812  };
2813 
2814  // Performs the actual concatenation by step-wise expanding tuple-like
2815  // objects into the elements, which are finally forwarded into the
2816  // result tuple.
2817  template<typename _Ret, typename _Indices, typename... _Tpls>
2818  struct __tuple_concater;
2819 
2820  template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2821  struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2822  {
2823  template<typename... _Us>
2824  static constexpr _Ret
2825  _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2826  {
2827  typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2828  typedef __tuple_concater<_Ret, __idx, _Tpls...> __next;
2829  return __next::_S_do(std::forward<_Tpls>(__tps)...,
2830  std::forward<_Us>(__us)...,
2831  std::get<_Is>(std::forward<_Tp>(__tp))...);
2832  }
2833  };
2834 
2835  template<typename _Ret>
2836  struct __tuple_concater<_Ret, _Index_tuple<>>
2837  {
2838  template<typename... _Us>
2839  static constexpr _Ret
2840  _S_do(_Us&&... __us)
2841  {
2842  return _Ret(std::forward<_Us>(__us)...);
2843  }
2844  };
2845 
2846  template<typename... _Tps>
2847  struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2848  { };
2849  /// @endcond
2850 
2851  /// Create a `tuple` containing all elements from multiple tuple-like objects
2852 #if __cpp_lib_tuple_like // >= C++23
2853  template<__tuple_like... _Tpls>
2854 #else
2855  template<typename... _Tpls, typename = typename
2856  enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2857 #endif
2858  constexpr auto
2859  tuple_cat(_Tpls&&... __tpls)
2860  -> typename __tuple_cat_result<_Tpls...>::__type
2861  {
2862  typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2863  typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2864  typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2865  return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2866  }
2867 
2868  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2869  // 2301. Why is tie not constexpr?
2870  /// Return a tuple of lvalue references bound to the arguments
2871  template<typename... _Elements>
2872  constexpr tuple<_Elements&...>
2873  tie(_Elements&... __args) noexcept
2874  { return tuple<_Elements&...>(__args...); }
2875 
2876  /// Exchange the values of two tuples
2877  template<typename... _Elements>
2878  _GLIBCXX20_CONSTEXPR
2879  inline
2880 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2881  // Constrained free swap overload, see p0185r1
2882  typename enable_if<__and_<__is_swappable<_Elements>...>::value
2883  >::type
2884 #else
2885  void
2886 #endif
2887  swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
2888  noexcept(noexcept(__x.swap(__y)))
2889  { __x.swap(__y); }
2890 
2891 #if __cpp_lib_ranges_zip // >= C++23
2892  /// Exchange the values of two const tuples (if const elements can be swapped)
2893  template<typename... _Elements>
2894  requires (is_swappable_v<const _Elements> && ...)
2895  constexpr void
2896  swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2897  noexcept(noexcept(__x.swap(__y)))
2898  { __x.swap(__y); }
2899 #endif // C++23
2900 
2901 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2902  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2903  // 2766. Swapping non-swappable types
2904  template<typename... _Elements>
2905  _GLIBCXX20_CONSTEXPR
2906  typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2907  swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2908 #endif
2909 
2910  /// Partial specialization for tuples
2911  template<typename... _Types, typename _Alloc>
2912  struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2913 
2914  // See stl_pair.h...
2915  /** "piecewise construction" using a tuple of arguments for each member.
2916  *
2917  * @param __first Arguments for the first member of the pair.
2918  * @param __second Arguments for the second member of the pair.
2919  *
2920  * The elements of each tuple will be used as the constructor arguments
2921  * for the data members of the pair.
2922  */
2923  template<class _T1, class _T2>
2924  template<typename... _Args1, typename... _Args2>
2925  _GLIBCXX20_CONSTEXPR
2926  inline
2929  tuple<_Args1...> __first, tuple<_Args2...> __second)
2930  : pair(__first, __second,
2931  typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2932  typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2933  { }
2934 
2935  template<class _T1, class _T2>
2936  template<typename... _Args1, size_t... _Indexes1,
2937  typename... _Args2, size_t... _Indexes2>
2938  _GLIBCXX20_CONSTEXPR inline
2940  pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2941  _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2942  : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2943  second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2944  { }
2945 
2946 #if defined(__cpp_lib_apply) || defined(__cpp_lib_make_from_tuple) // C++ >= 17
2947  // Unpack a std::tuple into a type trait and use its value.
2948  // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2949  // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2950  // Otherwise the result is false (because we don't know if std::get throws).
2951  template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2952  inline constexpr bool __unpack_std_tuple = false;
2953 
2954  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2955  inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2956  = _Trait<_Tp, _Up...>::value;
2957 
2958  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2959  inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2960  = _Trait<_Tp, _Up&...>::value;
2961 
2962  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2963  inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2964  = _Trait<_Tp, const _Up...>::value;
2965 
2966  template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2967  inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2968  = _Trait<_Tp, const _Up&...>::value;
2969 #endif
2970 
2971 #ifdef __cpp_lib_apply // C++ >= 17
2972  template <typename _Fn, typename _Tuple, size_t... _Idx>
2973  constexpr decltype(auto)
2974  __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2975  {
2976  return std::__invoke(std::forward<_Fn>(__f),
2977  std::get<_Idx>(std::forward<_Tuple>(__t))...);
2978  }
2979 
2980 #if __cpp_lib_tuple_like // >= C++23
2981  template <typename _Fn, __tuple_like _Tuple>
2982 #else
2983  template <typename _Fn, typename _Tuple>
2984 #endif
2985  constexpr decltype(auto)
2986  apply(_Fn&& __f, _Tuple&& __t)
2987  noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2988  {
2989  using _Indices
2990  = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2991  return std::__apply_impl(std::forward<_Fn>(__f),
2992  std::forward<_Tuple>(__t),
2993  _Indices{});
2994  }
2995 #endif
2996 
2997 #ifdef __cpp_lib_make_from_tuple // C++ >= 17
2998  template <typename _Tp, typename _Tuple, typename _Seq
2999  = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>>
3000  constexpr bool __can_make_from_tuple = false;
3001 
3002  // _GLIBCXX_RESOLVE_LIB_DEFECTS
3003  // 3528. make_from_tuple can perform (the equivalent of) a C-style cast
3004  template <typename _Tp, typename _Tuple, size_t... _Idx>
3005  constexpr bool __can_make_from_tuple<_Tp, _Tuple, index_sequence<_Idx...>>
3006  = is_constructible_v<_Tp,
3007  decltype(std::get<_Idx>(std::declval<_Tuple>()))...>;
3008 
3009  template <typename _Tp, typename _Tuple, size_t... _Idx>
3010  constexpr _Tp
3011  __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
3012  {
3013  static_assert(__can_make_from_tuple<_Tp, _Tuple, index_sequence<_Idx...>>);
3014  return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...);
3015  }
3016 
3017 #if __cpp_lib_tuple_like // >= C++23
3018  template <typename _Tp, __tuple_like _Tuple>
3019 #else
3020  template <typename _Tp, typename _Tuple>
3021 #endif
3022  constexpr auto
3023  make_from_tuple(_Tuple&& __t)
3024  noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
3025 #ifdef __cpp_concepts // >= C++20
3026  -> _Tp
3027  requires __can_make_from_tuple<_Tp, _Tuple>
3028 #else
3029  -> __enable_if_t<__can_make_from_tuple<_Tp, _Tuple>, _Tp>
3030 #endif
3031  {
3032  constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
3033 #if __has_builtin(__reference_constructs_from_temporary)
3034  if constexpr (__n == 1)
3035  {
3036  using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
3037  static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
3038  }
3039 #endif
3040  return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
3041  make_index_sequence<__n>{});
3042  }
3043 #endif
3044 
3045 #if __cpp_lib_tuple_like // >= C++23
3046  template<__tuple_like _TTuple, __tuple_like _UTuple,
3047  template<typename> class _TQual, template<typename> class _UQual,
3048  typename = make_index_sequence<tuple_size_v<_TTuple>>>
3049  struct __tuple_like_common_reference;
3050 
3051  template<__tuple_like _TTuple, __tuple_like _UTuple,
3052  template<typename> class _TQual, template<typename> class _UQual,
3053  size_t... _Is>
3054  requires requires
3055  { typename tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
3056  _UQual<tuple_element_t<_Is, _UTuple>>>...>; }
3057  struct __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual, index_sequence<_Is...>>
3058  {
3059  using type = tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
3060  _UQual<tuple_element_t<_Is, _UTuple>>>...>;
3061  };
3062 
3063  template<__tuple_like _TTuple, __tuple_like _UTuple,
3064  template<typename> class _TQual, template<typename> class _UQual>
3065  requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
3066  && is_same_v<_TTuple, decay_t<_TTuple>>
3067  && is_same_v<_UTuple, decay_t<_UTuple>>
3068  && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
3069  && requires { typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type; }
3070  struct basic_common_reference<_TTuple, _UTuple, _TQual, _UQual>
3071  {
3072  using type = typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type;
3073  };
3074 
3075  template<__tuple_like _TTuple, __tuple_like _UTuple,
3076  typename = make_index_sequence<tuple_size_v<_TTuple>>>
3077  struct __tuple_like_common_type;
3078 
3079  template<__tuple_like _TTuple, __tuple_like _UTuple, size_t... _Is>
3080  requires requires
3081  { typename tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3082  tuple_element_t<_Is, _UTuple>>...>; }
3083  struct __tuple_like_common_type<_TTuple, _UTuple, index_sequence<_Is...>>
3084  {
3085  using type = tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3086  tuple_element_t<_Is, _UTuple>>...>;
3087  };
3088 
3089  template<__tuple_like _TTuple, __tuple_like _UTuple>
3090  requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
3091  && is_same_v<_TTuple, decay_t<_TTuple>>
3092  && is_same_v<_UTuple, decay_t<_UTuple>>
3093  && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
3094  && requires { typename __tuple_like_common_type<_TTuple, _UTuple>::type; }
3095  struct common_type<_TTuple, _UTuple>
3096  {
3097  using type = typename __tuple_like_common_type<_TTuple, _UTuple>::type;
3098  };
3099 #endif // C++23
3100 
3101  /// @}
3102 
3103 #undef __glibcxx_no_dangling_refs
3104 
3105 _GLIBCXX_END_NAMESPACE_VERSION
3106 } // namespace std
3107 
3108 #endif // C++11
3109 
3110 #endif // _GLIBCXX_TUPLE
constexpr bool operator<=(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition: chrono.h:859
constexpr bool operator>=(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition: chrono.h:873
constexpr bool operator<(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition: chrono.h:826
constexpr bool operator>(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition: chrono.h:866
__bool_constant< true > true_type
The type used as a compile-time boolean with true value.
Definition: type_traits:119
__bool_constant< false > false_type
The type used as a compile-time boolean with false value.
Definition: type_traits:122
constexpr auto tuple_cat(_Tpls &&... __tpls) -> typename __tuple_cat_result< _Tpls... >::__type
Create a tuple containing all elements from multiple tuple-like objects.
Definition: tuple:2857
constexpr tuple< _Elements &... > tie(_Elements &... __args) noexcept
Return a tuple of lvalue references bound to the arguments.
Definition: tuple:2871
constexpr __invoke_result< _Callable, _Args... >::type __invoke(_Callable &&__fn, _Args &&... __args) noexcept(__is_nothrow_invocable< _Callable, _Args... >::value)
Invoke a callable object.
Definition: invoke.h:92
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:138
constexpr tuple< _Elements &&... > forward_as_tuple(_Elements &&... __args) noexcept
Create a tuple of lvalue or rvalue references to the arguments.
Definition: tuple:2733
constexpr tuple< typename __decay_and_strip< _Elements >::__type... > make_tuple(_Elements &&... __args)
Create a tuple containing copies of the arguments.
Definition: tuple:2721
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition: move.h:72
ISO C++ entities toplevel namespace is std.
make_integer_sequence< size_t, _Num > make_index_sequence
Alias template make_index_sequence.
Definition: utility.h:168
integer_sequence< size_t, _Idx... > index_sequence
Alias template index_sequence.
Definition: utility.h:164
make_index_sequence< sizeof...(_Types)> index_sequence_for
Alias template index_sequence_for.
Definition: utility.h:172
Primary class template, tuple.
Definition: tuple:834
Partial specialization, 2-element tuple. Includes construction and assignment from a pair.
Definition: tuple:2064
integral_constant
Definition: type_traits:96
is_same
Definition: type_traits:1623
is_nothrow_constructible
Definition: type_traits:1317
is_nothrow_default_constructible
Definition: type_traits:1326
is_assignable
Definition: type_traits:1358
is_nothrow_assignable
Definition: type_traits:1392
Declare uses_allocator so it can be specialized in <queue> etc.
Definition: memoryfwd.h:76
Struct holding two objects of arbitrary type.
Definition: stl_pair.h:304
constexpr pair(const pair &)=default
Copy constructor.
Tag type for piecewise construction of std::pair objects.
Definition: stl_pair.h:79
Finds the size of a given tuple type.
Definition: utility.h:51
Gives the type of the ith element of a given tuple type.
Definition: utility.h:82
Class template integer_sequence.
Definition: utility.h:145