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