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