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
56namespace 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>
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))
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...>())
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&...>())
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
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
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, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1554 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1555 _GLIBCXX20_CONSTEXPR
1556 tuple(allocator_arg_t __tag, const _Alloc& __a,
1557 const _Elements&... __elements)
1558 : _Inherited(__tag, __a, __elements...) { }
1559
1560 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1561 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1562 _GLIBCXX20_CONSTEXPR
1563 explicit
1564 tuple(allocator_arg_t __tag, const _Alloc& __a,
1565 const _Elements&... __elements)
1566 : _Inherited(__tag, __a, __elements...) { }
1567
1568 template<typename _Alloc, typename... _UElements,
1569 bool _Valid = __valid_args<_UElements...>(),
1570 _ImplicitCtor<_Valid, _UElements...> = true>
1571 _GLIBCXX20_CONSTEXPR
1572 tuple(allocator_arg_t __tag, const _Alloc& __a,
1573 _UElements&&... __elements)
1574 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1575 { __glibcxx_no_dangling_refs(_UElements&&); }
1576
1577 template<typename _Alloc, typename... _UElements,
1578 bool _Valid = __valid_args<_UElements...>(),
1579 _ExplicitCtor<_Valid, _UElements...> = false>
1580 _GLIBCXX20_CONSTEXPR
1581 explicit
1582 tuple(allocator_arg_t __tag, const _Alloc& __a,
1583 _UElements&&... __elements)
1584 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1585 { __glibcxx_no_dangling_refs(_UElements&&); }
1586
1587 template<typename _Alloc>
1588 _GLIBCXX20_CONSTEXPR
1589 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1590 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1591
1592 template<typename _Alloc>
1593 _GLIBCXX20_CONSTEXPR
1594 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1595 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1596
1597 template<typename _Alloc, typename... _UElements,
1598 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1599 && !__use_other_ctor<const tuple<_UElements...>&>(),
1600 _ImplicitCtor<_Valid, const _UElements&...> = true>
1601 _GLIBCXX20_CONSTEXPR
1602 tuple(allocator_arg_t __tag, const _Alloc& __a,
1603 const tuple<_UElements...>& __in)
1604 : _Inherited(__tag, __a,
1605 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1606 { __glibcxx_no_dangling_refs(const _UElements&); }
1607
1608 template<typename _Alloc, typename... _UElements,
1609 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1610 && !__use_other_ctor<const tuple<_UElements...>&>(),
1611 _ExplicitCtor<_Valid, const _UElements&...> = false>
1612 _GLIBCXX20_CONSTEXPR
1613 explicit
1614 tuple(allocator_arg_t __tag, const _Alloc& __a,
1615 const tuple<_UElements...>& __in)
1616 : _Inherited(__tag, __a,
1617 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1618 { __glibcxx_no_dangling_refs(const _UElements&); }
1619
1620 template<typename _Alloc, typename... _UElements,
1621 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1622 && !__use_other_ctor<tuple<_UElements...>&&>(),
1623 _ImplicitCtor<_Valid, _UElements...> = true>
1624 _GLIBCXX20_CONSTEXPR
1625 tuple(allocator_arg_t __tag, const _Alloc& __a,
1626 tuple<_UElements...>&& __in)
1627 : _Inherited(__tag, __a,
1628 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1629 { __glibcxx_no_dangling_refs(_UElements&&); }
1630
1631 template<typename _Alloc, typename... _UElements,
1632 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1633 && !__use_other_ctor<tuple<_UElements...>&&>(),
1634 _ExplicitCtor<_Valid, _UElements...> = false>
1635 _GLIBCXX20_CONSTEXPR
1636 explicit
1637 tuple(allocator_arg_t __tag, const _Alloc& __a,
1638 tuple<_UElements...>&& __in)
1639 : _Inherited(__tag, __a,
1640 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1641 { __glibcxx_no_dangling_refs(_UElements&&); }
1642#endif // concepts && conditional_explicit
1643
1644 // tuple assignment
1645
1646#if __cpp_concepts && __cpp_consteval // >= C++20
1647 private:
1648 template<typename... _UTypes>
1649 static consteval bool
1650 __assignable()
1651 {
1652 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1653 return __and_v<is_assignable<_Elements&, _UTypes>...>;
1654 else
1655 return false;
1656 }
1657
1658 template<typename... _UTypes>
1659 static consteval bool
1660 __nothrow_assignable()
1661 {
1662 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1664 else
1665 return false;
1666 }
1667
1668#if __cpp_lib_ranges_zip // >= C++23
1669 template<typename... _UTypes>
1670 static consteval bool
1671 __const_assignable()
1672 {
1673 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1675 else
1676 return false;
1677 }
1678#endif // C++23
1679
1680#if __cpp_lib_tuple_like // >= C++23
1681 template<typename _UTuple>
1682 static consteval bool
1683 __assignable_from_tuple_like()
1684 {
1685 return []<size_t... _Is>(index_sequence<_Is...>) {
1686 return __assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1687 }(index_sequence_for<_Elements...>{});
1688 }
1689
1690 template<typename _UTuple>
1691 static consteval bool
1692 __const_assignable_from_tuple_like()
1693 {
1694 return []<size_t... _Is>(index_sequence<_Is...>) {
1695 return __const_assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1696 }(index_sequence_for<_Elements...>{});
1697 }
1698#endif // C++23
1699
1700 public:
1701
1702 tuple& operator=(const tuple& __u) = delete;
1703
1704 constexpr tuple&
1705 operator=(const tuple& __u)
1706 noexcept(__nothrow_assignable<const _Elements&...>())
1707 requires (__assignable<const _Elements&...>())
1708 {
1709 this->_M_assign(__u);
1710 return *this;
1711 }
1712
1713 constexpr tuple&
1714 operator=(tuple&& __u)
1715 noexcept(__nothrow_assignable<_Elements...>())
1716 requires (__assignable<_Elements...>())
1717 {
1718 this->_M_assign(std::move(__u));
1719 return *this;
1720 }
1721
1722 template<typename... _UTypes>
1723 requires (__assignable<const _UTypes&...>())
1724 constexpr tuple&
1725 operator=(const tuple<_UTypes...>& __u)
1726 noexcept(__nothrow_assignable<const _UTypes&...>())
1727 {
1728 this->_M_assign(__u);
1729 return *this;
1730 }
1731
1732 template<typename... _UTypes>
1733 requires (__assignable<_UTypes...>())
1734 constexpr tuple&
1735 operator=(tuple<_UTypes...>&& __u)
1736 noexcept(__nothrow_assignable<_UTypes...>())
1737 {
1738 this->_M_assign(std::move(__u));
1739 return *this;
1740 }
1741
1742#if __cpp_lib_ranges_zip // >= C++23
1743 constexpr const tuple&
1744 operator=(const tuple& __u) const
1745 requires (__const_assignable<const _Elements&...>())
1746 {
1747 this->_M_assign(__u);
1748 return *this;
1749 }
1750
1751 constexpr const tuple&
1752 operator=(tuple&& __u) const
1753 requires (__const_assignable<_Elements...>())
1754 {
1755 this->_M_assign(std::move(__u));
1756 return *this;
1757 }
1758
1759 template<typename... _UTypes>
1760 constexpr const tuple&
1761 operator=(const tuple<_UTypes...>& __u) const
1762 requires (__const_assignable<const _UTypes&...>())
1763 {
1764 this->_M_assign(__u);
1765 return *this;
1766 }
1767
1768 template<typename... _UTypes>
1769 constexpr const tuple&
1770 operator=(tuple<_UTypes...>&& __u) const
1771 requires (__const_assignable<_UTypes...>())
1772 {
1773 this->_M_assign(std::move(__u));
1774 return *this;
1775 }
1776#endif // C++23
1777
1778 template<typename _U1, typename _U2>
1779 requires (__assignable<const _U1&, const _U2&>())
1780 constexpr tuple&
1781 operator=(const pair<_U1, _U2>& __u)
1782 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1783 {
1784 this->_M_head(*this) = __u.first;
1785 this->_M_tail(*this)._M_head(*this) = __u.second;
1786 return *this;
1787 }
1788
1789 template<typename _U1, typename _U2>
1790 requires (__assignable<_U1, _U2>())
1791 constexpr tuple&
1792 operator=(pair<_U1, _U2>&& __u)
1793 noexcept(__nothrow_assignable<_U1, _U2>())
1794 {
1795 this->_M_head(*this) = std::forward<_U1>(__u.first);
1796 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1797 return *this;
1798 }
1799
1800#if __cpp_lib_ranges_zip // >= C++23
1801 template<typename _U1, typename _U2>
1802 requires (__const_assignable<const _U1&, const _U2>())
1803 constexpr const tuple&
1804 operator=(const pair<_U1, _U2>& __u) const
1805 {
1806 this->_M_head(*this) = __u.first;
1807 this->_M_tail(*this)._M_head(*this) = __u.second;
1808 return *this;
1809 }
1810
1811 template<typename _U1, typename _U2>
1812 requires (__const_assignable<_U1, _U2>())
1813 constexpr const tuple&
1814 operator=(pair<_U1, _U2>&& __u) const
1815 {
1816 this->_M_head(*this) = std::forward<_U1>(__u.first);
1817 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1818 return *this;
1819 }
1820#endif // C++23
1821
1822#if __cpp_lib_tuple_like // >= C++23
1823 template<__eligible_tuple_like<tuple> _UTuple>
1824 requires (__assignable_from_tuple_like<_UTuple>())
1825 constexpr tuple&
1826 operator=(_UTuple&& __u)
1827 {
1828 this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1829 return *this;
1830 }
1831
1832 template<__eligible_tuple_like<tuple> _UTuple>
1833 requires (__const_assignable_from_tuple_like<_UTuple>())
1834 constexpr const tuple&
1835 operator=(_UTuple&& __u) const
1836 {
1837 this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1838 return *this;
1839 }
1840
1841 template<__tuple_like _UTuple>
1842 requires (!__is_tuple_v<_UTuple>)
1843 friend constexpr bool
1844 operator==(const tuple& __t, const _UTuple& __u)
1845 {
1846 static_assert(sizeof...(_Elements) == tuple_size_v<_UTuple>,
1847 "tuple objects can only be compared if they have equal sizes.");
1848 return [&]<size_t... _Is>(index_sequence<_Is...>) {
1849 return (bool(std::get<_Is>(__t) == std::get<_Is>(__u))
1850 && ...);
1851 }(index_sequence_for<_Elements...>{});
1852 }
1853
1854 template<__tuple_like _UTuple,
1856 struct __tuple_like_common_comparison_category;
1857
1858 template<__tuple_like _UTuple, size_t... _Is>
1859 requires requires
1860 { typename void_t<__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>; }
1861 struct __tuple_like_common_comparison_category<_UTuple, index_sequence<_Is...>>
1862 {
1863 using type = common_comparison_category_t
1864 <__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>;
1865 };
1866
1867 template<__tuple_like _UTuple>
1868 requires (!__is_tuple_v<_UTuple>)
1869 friend constexpr typename __tuple_like_common_comparison_category<_UTuple>::type
1870 operator<=>(const tuple& __t, const _UTuple& __u)
1871 {
1872 using _Cat = typename __tuple_like_common_comparison_category<_UTuple>::type;
1873 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Elements...>());
1874 }
1875#endif // C++23
1876
1877#else // ! (concepts && consteval)
1878
1879 private:
1880 template<typename... _UElements>
1881 static constexpr
1882 __enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
1883 __assignable()
1884 { return __and_<is_assignable<_Elements&, _UElements>...>::value; }
1885
1886 // Condition for noexcept-specifier of an assignment operator.
1887 template<typename... _UElements>
1888 static constexpr bool __nothrow_assignable()
1889 {
1890 return
1891 __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
1892 }
1893
1894 public:
1895
1896 _GLIBCXX20_CONSTEXPR
1897 tuple&
1898 operator=(__conditional_t<__assignable<const _Elements&...>(),
1899 const tuple&,
1900 const __nonesuch&> __in)
1901 noexcept(__nothrow_assignable<const _Elements&...>())
1902 {
1903 this->_M_assign(__in);
1904 return *this;
1905 }
1906
1907 _GLIBCXX20_CONSTEXPR
1908 tuple&
1909 operator=(__conditional_t<__assignable<_Elements...>(),
1910 tuple&&,
1911 __nonesuch&&> __in)
1912 noexcept(__nothrow_assignable<_Elements...>())
1913 {
1914 this->_M_assign(std::move(__in));
1915 return *this;
1916 }
1917
1918 template<typename... _UElements>
1919 _GLIBCXX20_CONSTEXPR
1920 __enable_if_t<__assignable<const _UElements&...>(), tuple&>
1921 operator=(const tuple<_UElements...>& __in)
1922 noexcept(__nothrow_assignable<const _UElements&...>())
1923 {
1924 this->_M_assign(__in);
1925 return *this;
1926 }
1927
1928 template<typename... _UElements>
1929 _GLIBCXX20_CONSTEXPR
1930 __enable_if_t<__assignable<_UElements...>(), tuple&>
1931 operator=(tuple<_UElements...>&& __in)
1932 noexcept(__nothrow_assignable<_UElements...>())
1933 {
1934 this->_M_assign(std::move(__in));
1935 return *this;
1936 }
1937#endif // concepts && consteval
1938
1939 // tuple swap
1940 _GLIBCXX20_CONSTEXPR
1941 void
1942 swap(tuple& __in)
1943 noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
1944 { _Inherited::_M_swap(__in); }
1945
1946#if __cpp_lib_ranges_zip // >= C++23
1947 // As an extension, we constrain the const swap member function in order
1948 // to continue accepting explicit instantiation of tuples whose elements
1949 // are not all const swappable. Without this constraint, such an
1950 // explicit instantiation would also instantiate the ill-formed body of
1951 // this function and yield a hard error. This constraint shouldn't
1952 // affect the behavior of valid programs.
1953 constexpr void
1954 swap(const tuple& __in) const
1955 noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
1956 requires (is_swappable_v<const _Elements> && ...)
1957 { _Inherited::_M_swap(__in); }
1958#endif // C++23
1959 };
1960
1961#if __cpp_deduction_guides >= 201606
1962 template<typename... _UTypes>
1963 tuple(_UTypes...) -> tuple<_UTypes...>;
1964 template<typename _T1, typename _T2>
1966 template<typename _Alloc, typename... _UTypes>
1967 tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
1968 template<typename _Alloc, typename _T1, typename _T2>
1969 tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
1970 template<typename _Alloc, typename... _UTypes>
1971 tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
1972#endif
1973
1974 // Explicit specialization, zero-element tuple.
1975 template<>
1976 class tuple<>
1977 {
1978 public:
1979 _GLIBCXX20_CONSTEXPR
1980 void swap(tuple&) noexcept { /* no-op */ }
1981#if __cpp_lib_ranges_zip // >= C++23
1982 constexpr void swap(const tuple&) const noexcept { /* no-op */ }
1983#endif
1984 // We need the default since we're going to define no-op
1985 // allocator constructors.
1986 tuple() = default;
1987 // No-op allocator constructors.
1988 template<typename _Alloc>
1989 _GLIBCXX20_CONSTEXPR
1990 tuple(allocator_arg_t, const _Alloc&) noexcept { }
1991 template<typename _Alloc>
1992 _GLIBCXX20_CONSTEXPR
1993 tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
1994 };
1995
1996#if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20
1997 /// Partial specialization, 2-element tuple.
1998 /// Includes construction and assignment from a pair.
1999 template<typename _T1, typename _T2>
2000 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
2001 {
2003
2004 // Constraint for non-explicit default constructor
2005 template<bool _Dummy, typename _U1, typename _U2>
2006 using _ImplicitDefaultCtor = __enable_if_t<
2007 _TupleConstraints<_Dummy, _U1, _U2>::
2008 __is_implicitly_default_constructible(),
2009 bool>;
2010
2011 // Constraint for explicit default constructor
2012 template<bool _Dummy, typename _U1, typename _U2>
2013 using _ExplicitDefaultCtor = __enable_if_t<
2014 _TupleConstraints<_Dummy, _U1, _U2>::
2015 __is_explicitly_default_constructible(),
2016 bool>;
2017
2018 template<bool _Dummy>
2019 using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
2020
2021 // Constraint for non-explicit constructors
2022 template<bool _Cond, typename _U1, typename _U2>
2023 using _ImplicitCtor = __enable_if_t<
2024 _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
2025 bool>;
2026
2027 // Constraint for non-explicit constructors
2028 template<bool _Cond, typename _U1, typename _U2>
2029 using _ExplicitCtor = __enable_if_t<
2030 _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
2031 bool>;
2032
2033 template<typename _U1, typename _U2>
2034 static constexpr bool __assignable()
2035 {
2036 return __and_<is_assignable<_T1&, _U1>,
2038 }
2039
2040 template<typename _U1, typename _U2>
2041 static constexpr bool __nothrow_assignable()
2042 {
2043 return __and_<is_nothrow_assignable<_T1&, _U1>,
2045 }
2046
2047 template<typename _U1, typename _U2>
2048 static constexpr bool __nothrow_constructible()
2049 {
2050 return __and_<is_nothrow_constructible<_T1, _U1>,
2052 }
2053
2054 static constexpr bool __nothrow_default_constructible()
2055 {
2056 return __and_<is_nothrow_default_constructible<_T1>,
2058 }
2059
2060 template<typename _U1>
2061 static constexpr bool __is_alloc_arg()
2062 { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
2063
2064 /// @cond undocumented
2065#undef __glibcxx_no_dangling_refs
2066 // Error if construction from _U1 and _U2 would create a dangling ref.
2067#if __has_builtin(__reference_constructs_from_temporary) \
2068 && defined _GLIBCXX_DEBUG
2069# define __glibcxx_no_dangling_refs(_U1, _U2) \
2070 static_assert(!__reference_constructs_from_temporary(_T1, _U1) \
2071 && !__reference_constructs_from_temporary(_T2, _U2), \
2072 "std::tuple constructor creates a dangling reference")
2073#else
2074# define __glibcxx_no_dangling_refs(_U1, _U2)
2075#endif
2076 /// @endcond
2077
2078 public:
2079 template<bool _Dummy = true,
2080 _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
2081 constexpr
2082 tuple()
2083 noexcept(__nothrow_default_constructible())
2084 : _Inherited() { }
2085
2086 template<bool _Dummy = true,
2087 _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
2088 explicit constexpr
2089 tuple()
2090 noexcept(__nothrow_default_constructible())
2091 : _Inherited() { }
2092
2093 template<bool _Dummy = true,
2094 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2095 constexpr
2096 tuple(const _T1& __a1, const _T2& __a2)
2097 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2098 : _Inherited(__a1, __a2) { }
2099
2100 template<bool _Dummy = true,
2101 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2102 explicit constexpr
2103 tuple(const _T1& __a1, const _T2& __a2)
2104 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2105 : _Inherited(__a1, __a2) { }
2106
2107 template<typename _U1, typename _U2,
2108 _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
2109 constexpr
2110 tuple(_U1&& __a1, _U2&& __a2)
2111 noexcept(__nothrow_constructible<_U1, _U2>())
2112 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2113 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2114
2115 template<typename _U1, typename _U2,
2116 _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
2117 explicit constexpr
2118 tuple(_U1&& __a1, _U2&& __a2)
2119 noexcept(__nothrow_constructible<_U1, _U2>())
2120 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2121 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2122
2123 constexpr tuple(const tuple&) = default;
2124
2125 constexpr tuple(tuple&&) = default;
2126
2127 template<typename _U1, typename _U2,
2128 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2129 constexpr
2130 tuple(const tuple<_U1, _U2>& __in)
2131 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2132 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2133 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2134
2135 template<typename _U1, typename _U2,
2136 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2137 explicit constexpr
2138 tuple(const tuple<_U1, _U2>& __in)
2139 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2140 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2141 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2142
2143 template<typename _U1, typename _U2,
2144 _ImplicitCtor<true, _U1, _U2> = true>
2145 constexpr
2146 tuple(tuple<_U1, _U2>&& __in)
2147 noexcept(__nothrow_constructible<_U1, _U2>())
2148 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2149 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2150
2151 template<typename _U1, typename _U2,
2152 _ExplicitCtor<true, _U1, _U2> = false>
2153 explicit constexpr
2154 tuple(tuple<_U1, _U2>&& __in)
2155 noexcept(__nothrow_constructible<_U1, _U2>())
2156 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2157 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2158
2159 template<typename _U1, typename _U2,
2160 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2161 constexpr
2162 tuple(const pair<_U1, _U2>& __in)
2163 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2164 : _Inherited(__in.first, __in.second)
2165 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2166
2167 template<typename _U1, typename _U2,
2168 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2169 explicit constexpr
2170 tuple(const pair<_U1, _U2>& __in)
2171 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2172 : _Inherited(__in.first, __in.second)
2173 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2174
2175 template<typename _U1, typename _U2,
2176 _ImplicitCtor<true, _U1, _U2> = true>
2177 constexpr
2178 tuple(pair<_U1, _U2>&& __in)
2179 noexcept(__nothrow_constructible<_U1, _U2>())
2180 : _Inherited(std::forward<_U1>(__in.first),
2181 std::forward<_U2>(__in.second))
2182 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2183
2184 template<typename _U1, typename _U2,
2185 _ExplicitCtor<true, _U1, _U2> = false>
2186 explicit constexpr
2187 tuple(pair<_U1, _U2>&& __in)
2188 noexcept(__nothrow_constructible<_U1, _U2>())
2189 : _Inherited(std::forward<_U1>(__in.first),
2190 std::forward<_U2>(__in.second))
2191 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2192
2193 // Allocator-extended constructors.
2194
2195 template<typename _Alloc,
2196 _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
2197 _GLIBCXX20_CONSTEXPR
2198 tuple(allocator_arg_t __tag, const _Alloc& __a)
2199 : _Inherited(__tag, __a) { }
2200
2201 template<typename _Alloc, bool _Dummy = true,
2202 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2203 _GLIBCXX20_CONSTEXPR
2204 tuple(allocator_arg_t __tag, const _Alloc& __a,
2205 const _T1& __a1, const _T2& __a2)
2206 : _Inherited(__tag, __a, __a1, __a2) { }
2207
2208 template<typename _Alloc, bool _Dummy = true,
2209 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2210 explicit
2211 _GLIBCXX20_CONSTEXPR
2212 tuple(allocator_arg_t __tag, const _Alloc& __a,
2213 const _T1& __a1, const _T2& __a2)
2214 : _Inherited(__tag, __a, __a1, __a2) { }
2215
2216 template<typename _Alloc, typename _U1, typename _U2,
2217 _ImplicitCtor<true, _U1, _U2> = true>
2218 _GLIBCXX20_CONSTEXPR
2219 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
2220 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2221 std::forward<_U2>(__a2))
2222 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2223
2224 template<typename _Alloc, typename _U1, typename _U2,
2225 _ExplicitCtor<true, _U1, _U2> = false>
2226 explicit
2227 _GLIBCXX20_CONSTEXPR
2228 tuple(allocator_arg_t __tag, const _Alloc& __a,
2229 _U1&& __a1, _U2&& __a2)
2230 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2231 std::forward<_U2>(__a2))
2232 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2233
2234 template<typename _Alloc>
2235 _GLIBCXX20_CONSTEXPR
2236 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
2237 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
2238
2239 template<typename _Alloc>
2240 _GLIBCXX20_CONSTEXPR
2241 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
2242 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
2243
2244 template<typename _Alloc, typename _U1, typename _U2,
2245 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2246 _GLIBCXX20_CONSTEXPR
2247 tuple(allocator_arg_t __tag, const _Alloc& __a,
2248 const tuple<_U1, _U2>& __in)
2249 : _Inherited(__tag, __a,
2250 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2251 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2252
2253 template<typename _Alloc, typename _U1, typename _U2,
2254 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2255 explicit
2256 _GLIBCXX20_CONSTEXPR
2257 tuple(allocator_arg_t __tag, const _Alloc& __a,
2258 const tuple<_U1, _U2>& __in)
2259 : _Inherited(__tag, __a,
2260 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2261 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2262
2263 template<typename _Alloc, typename _U1, typename _U2,
2264 _ImplicitCtor<true, _U1, _U2> = true>
2265 _GLIBCXX20_CONSTEXPR
2266 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2267 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2268 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2269
2270 template<typename _Alloc, typename _U1, typename _U2,
2271 _ExplicitCtor<true, _U1, _U2> = false>
2272 explicit
2273 _GLIBCXX20_CONSTEXPR
2274 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2275 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2276 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2277
2278 template<typename _Alloc, typename _U1, typename _U2,
2279 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2280 _GLIBCXX20_CONSTEXPR
2281 tuple(allocator_arg_t __tag, const _Alloc& __a,
2282 const pair<_U1, _U2>& __in)
2283 : _Inherited(__tag, __a, __in.first, __in.second)
2284 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2285
2286 template<typename _Alloc, typename _U1, typename _U2,
2287 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2288 explicit
2289 _GLIBCXX20_CONSTEXPR
2290 tuple(allocator_arg_t __tag, const _Alloc& __a,
2291 const pair<_U1, _U2>& __in)
2292 : _Inherited(__tag, __a, __in.first, __in.second)
2293 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2294
2295 template<typename _Alloc, typename _U1, typename _U2,
2296 _ImplicitCtor<true, _U1, _U2> = true>
2297 _GLIBCXX20_CONSTEXPR
2298 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2299 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2300 std::forward<_U2>(__in.second))
2301 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2302
2303 template<typename _Alloc, typename _U1, typename _U2,
2304 _ExplicitCtor<true, _U1, _U2> = false>
2305 explicit
2306 _GLIBCXX20_CONSTEXPR
2307 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2308 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2309 std::forward<_U2>(__in.second))
2310 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2311
2312 // Tuple assignment.
2313
2314 _GLIBCXX20_CONSTEXPR
2315 tuple&
2316 operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
2317 const tuple&,
2318 const __nonesuch&> __in)
2319 noexcept(__nothrow_assignable<const _T1&, const _T2&>())
2320 {
2321 this->_M_assign(__in);
2322 return *this;
2323 }
2324
2325 _GLIBCXX20_CONSTEXPR
2326 tuple&
2327 operator=(__conditional_t<__assignable<_T1, _T2>(),
2328 tuple&&,
2329 __nonesuch&&> __in)
2330 noexcept(__nothrow_assignable<_T1, _T2>())
2331 {
2332 this->_M_assign(std::move(__in));
2333 return *this;
2334 }
2335
2336 template<typename _U1, typename _U2>
2337 _GLIBCXX20_CONSTEXPR
2338 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2339 operator=(const tuple<_U1, _U2>& __in)
2340 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2341 {
2342 this->_M_assign(__in);
2343 return *this;
2344 }
2345
2346 template<typename _U1, typename _U2>
2347 _GLIBCXX20_CONSTEXPR
2348 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2349 operator=(tuple<_U1, _U2>&& __in)
2350 noexcept(__nothrow_assignable<_U1, _U2>())
2351 {
2352 this->_M_assign(std::move(__in));
2353 return *this;
2354 }
2355
2356 template<typename _U1, typename _U2>
2357 _GLIBCXX20_CONSTEXPR
2358 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2359 operator=(const pair<_U1, _U2>& __in)
2360 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2361 {
2362 this->_M_head(*this) = __in.first;
2363 this->_M_tail(*this)._M_head(*this) = __in.second;
2364 return *this;
2365 }
2366
2367 template<typename _U1, typename _U2>
2368 _GLIBCXX20_CONSTEXPR
2369 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2370 operator=(pair<_U1, _U2>&& __in)
2371 noexcept(__nothrow_assignable<_U1, _U2>())
2372 {
2373 this->_M_head(*this) = std::forward<_U1>(__in.first);
2374 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
2375 return *this;
2376 }
2377
2378 _GLIBCXX20_CONSTEXPR
2379 void
2380 swap(tuple& __in)
2381 noexcept(__and_<__is_nothrow_swappable<_T1>,
2382 __is_nothrow_swappable<_T2>>::value)
2383 { _Inherited::_M_swap(__in); }
2384 };
2385#endif // concepts && conditional_explicit
2386
2387 /// class tuple_size
2388 template<typename... _Elements>
2389 struct tuple_size<tuple<_Elements...>>
2390 : public integral_constant<size_t, sizeof...(_Elements)> { };
2391
2392#if __cplusplus >= 201703L
2393 template<typename... _Types>
2394 inline constexpr size_t tuple_size_v<tuple<_Types...>>
2395 = sizeof...(_Types);
2396
2397 template<typename... _Types>
2398 inline constexpr size_t tuple_size_v<const tuple<_Types...>>
2399 = sizeof...(_Types);
2400#endif
2401
2402 /// Trait to get the Ith element type from a tuple.
2403 template<size_t __i, typename... _Types>
2404 struct tuple_element<__i, tuple<_Types...>>
2405 {
2406 static_assert(__i < sizeof...(_Types), "tuple index must be in range");
2407
2408 using type = typename _Nth_type<__i, _Types...>::type;
2409 };
2410
2411 template<size_t __i, typename _Head, typename... _Tail>
2412 constexpr _Head&
2413 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2415
2416 template<size_t __i, typename _Head, typename... _Tail>
2417 constexpr const _Head&
2418 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2419 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2420
2421 // Deleted overload to improve diagnostics for invalid indices
2422 template<size_t __i, typename... _Types>
2423 __enable_if_t<(__i >= sizeof...(_Types))>
2424 __get_helper(const tuple<_Types...>&) = delete;
2425
2426 /// Return a reference to the ith element of a tuple.
2427 template<size_t __i, typename... _Elements>
2428 constexpr __tuple_element_t<__i, tuple<_Elements...>>&
2429 get(tuple<_Elements...>& __t) noexcept
2430 { return std::__get_helper<__i>(__t); }
2431
2432 /// Return a const reference to the ith element of a const tuple.
2433 template<size_t __i, typename... _Elements>
2434 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
2435 get(const tuple<_Elements...>& __t) noexcept
2436 { return std::__get_helper<__i>(__t); }
2437
2438 /// Return an rvalue reference to the ith element of a tuple rvalue.
2439 template<size_t __i, typename... _Elements>
2440 constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
2441 get(tuple<_Elements...>&& __t) noexcept
2442 {
2443 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2444 return std::forward<__element_type>(std::__get_helper<__i>(__t));
2445 }
2446
2447 /// Return a const rvalue reference to the ith element of a const tuple rvalue.
2448 template<size_t __i, typename... _Elements>
2449 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
2450 get(const tuple<_Elements...>&& __t) noexcept
2451 {
2452 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2453 return std::forward<const __element_type>(std::__get_helper<__i>(__t));
2454 }
2455
2456 /// @cond undocumented
2457 // Deleted overload chosen for invalid indices.
2458 template<size_t __i, typename... _Elements>
2459 constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
2460 get(const tuple<_Elements...>&) = delete;
2461 /// @endcond
2462
2463#ifdef __cpp_lib_tuples_by_type // C++ >= 14
2464 /// Return a reference to the unique element of type _Tp of a tuple.
2465 template <typename _Tp, typename... _Types>
2466 constexpr _Tp&
2467 get(tuple<_Types...>& __t) noexcept
2468 {
2469 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2470 static_assert(__idx < sizeof...(_Types),
2471 "the type T in std::get<T> must occur exactly once in the tuple");
2472 return std::__get_helper<__idx>(__t);
2473 }
2474
2475 /// Return a reference to the unique element of type _Tp of a tuple rvalue.
2476 template <typename _Tp, typename... _Types>
2477 constexpr _Tp&&
2478 get(tuple<_Types...>&& __t) noexcept
2479 {
2480 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2481 static_assert(__idx < sizeof...(_Types),
2482 "the type T in std::get<T> must occur exactly once in the tuple");
2483 return std::forward<_Tp>(std::__get_helper<__idx>(__t));
2484 }
2485
2486 /// Return a const reference to the unique element of type _Tp of a tuple.
2487 template <typename _Tp, typename... _Types>
2488 constexpr const _Tp&
2489 get(const tuple<_Types...>& __t) noexcept
2490 {
2491 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2492 static_assert(__idx < sizeof...(_Types),
2493 "the type T in std::get<T> must occur exactly once in the tuple");
2494 return std::__get_helper<__idx>(__t);
2495 }
2496
2497 /// Return a const reference to the unique element of type _Tp of
2498 /// a const tuple rvalue.
2499 template <typename _Tp, typename... _Types>
2500 constexpr const _Tp&&
2501 get(const tuple<_Types...>&& __t) noexcept
2502 {
2503 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2504 static_assert(__idx < sizeof...(_Types),
2505 "the type T in std::get<T> must occur exactly once in the tuple");
2506 return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
2507 }
2508#endif
2509
2510 // This class performs the comparison operations on tuples
2511 template<typename _Tp, typename _Up, size_t __i, size_t __size>
2512 struct __tuple_compare
2513 {
2514 static constexpr bool
2515 __eq(const _Tp& __t, const _Up& __u)
2516 {
2517 return bool(std::get<__i>(__t) == std::get<__i>(__u))
2518 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
2519 }
2520
2521 static constexpr bool
2522 __less(const _Tp& __t, const _Up& __u)
2523 {
2524 return bool(std::get<__i>(__t) < std::get<__i>(__u))
2525 || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
2526 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
2527 }
2528 };
2529
2530 template<typename _Tp, typename _Up, size_t __size>
2531 struct __tuple_compare<_Tp, _Up, __size, __size>
2532 {
2533 static constexpr bool
2534 __eq(const _Tp&, const _Up&) { return true; }
2535
2536 static constexpr bool
2537 __less(const _Tp&, const _Up&) { return false; }
2538 };
2539
2540 template<typename... _TElements, typename... _UElements>
2541 constexpr bool
2542 operator==(const tuple<_TElements...>& __t,
2543 const tuple<_UElements...>& __u)
2544 {
2545 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2546 "tuple objects can only be compared if they have equal sizes.");
2547 using __compare = __tuple_compare<tuple<_TElements...>,
2548 tuple<_UElements...>,
2549 0, sizeof...(_TElements)>;
2550 return __compare::__eq(__t, __u);
2551 }
2552
2553#if __cpp_lib_three_way_comparison
2554 template<typename _Cat, typename _Tp, typename _Up>
2555 constexpr _Cat
2556 __tuple_cmp(const _Tp&, const _Up&, index_sequence<>)
2557 { return _Cat::equivalent; }
2558
2559 template<typename _Cat, typename _Tp, typename _Up,
2560 size_t _Idx0, size_t... _Idxs>
2561 constexpr _Cat
2562 __tuple_cmp(const _Tp& __t, const _Up& __u,
2563 index_sequence<_Idx0, _Idxs...>)
2564 {
2565 auto __c
2566 = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u));
2567 if (__c != 0)
2568 return __c;
2569 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>());
2570 }
2571
2572 template<typename... _Tps, typename... _Ups>
2573 constexpr
2574 common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
2575 operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
2576 {
2577 using _Cat
2578 = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
2579 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
2580 }
2581#else
2582 template<typename... _TElements, typename... _UElements>
2583 constexpr bool
2584 operator<(const tuple<_TElements...>& __t,
2585 const tuple<_UElements...>& __u)
2586 {
2587 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2588 "tuple objects can only be compared if they have equal sizes.");
2589 using __compare = __tuple_compare<tuple<_TElements...>,
2590 tuple<_UElements...>,
2591 0, sizeof...(_TElements)>;
2592 return __compare::__less(__t, __u);
2593 }
2594
2595 template<typename... _TElements, typename... _UElements>
2596 constexpr bool
2597 operator!=(const tuple<_TElements...>& __t,
2598 const tuple<_UElements...>& __u)
2599 { return !(__t == __u); }
2600
2601 template<typename... _TElements, typename... _UElements>
2602 constexpr bool
2603 operator>(const tuple<_TElements...>& __t,
2604 const tuple<_UElements...>& __u)
2605 { return __u < __t; }
2606
2607 template<typename... _TElements, typename... _UElements>
2608 constexpr bool
2609 operator<=(const tuple<_TElements...>& __t,
2610 const tuple<_UElements...>& __u)
2611 { return !(__u < __t); }
2612
2613 template<typename... _TElements, typename... _UElements>
2614 constexpr bool
2615 operator>=(const tuple<_TElements...>& __t,
2616 const tuple<_UElements...>& __u)
2617 { return !(__t < __u); }
2618#endif // three_way_comparison
2619
2620 // NB: DR 705.
2621 /// Create a tuple containing copies of the arguments
2622 template<typename... _Elements>
2623 constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
2624 make_tuple(_Elements&&... __args)
2625 {
2627 __result_type;
2628 return __result_type(std::forward<_Elements>(__args)...);
2629 }
2630
2631 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2632 // 2275. Why is forward_as_tuple not constexpr?
2633 /// Create a tuple of lvalue or rvalue references to the arguments
2634 template<typename... _Elements>
2635 constexpr tuple<_Elements&&...>
2636 forward_as_tuple(_Elements&&... __args) noexcept
2637 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2638
2639 /// @cond undocumented
2640 template<size_t, typename, typename, size_t>
2641 struct __make_tuple_impl;
2642
2643 template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
2644 struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
2645 : __make_tuple_impl<_Idx + 1,
2646 tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
2647 _Tuple, _Nm>
2648 { };
2649
2650 template<size_t _Nm, typename _Tuple, typename... _Tp>
2651 struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
2652 {
2653 typedef tuple<_Tp...> __type;
2654 };
2655
2656 template<typename _Tuple>
2657 struct __do_make_tuple
2658 : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
2659 { };
2660
2661 // Returns the std::tuple equivalent of a tuple-like type.
2662 template<typename _Tuple>
2663 struct __make_tuple
2664 : public __do_make_tuple<__remove_cvref_t<_Tuple>>
2665 { };
2666
2667 // Combines several std::tuple's into a single one.
2668 template<typename...>
2669 struct __combine_tuples;
2670
2671 template<>
2672 struct __combine_tuples<>
2673 {
2674 typedef tuple<> __type;
2675 };
2676
2677 template<typename... _Ts>
2678 struct __combine_tuples<tuple<_Ts...>>
2679 {
2680 typedef tuple<_Ts...> __type;
2681 };
2682
2683 template<typename... _T1s, typename... _T2s, typename... _Rem>
2684 struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
2685 {
2686 typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
2687 _Rem...>::__type __type;
2688 };
2689
2690 // Computes the result type of tuple_cat given a set of tuple-like types.
2691 template<typename... _Tpls>
2692 struct __tuple_cat_result
2693 {
2694 typedef typename __combine_tuples
2695 <typename __make_tuple<_Tpls>::__type...>::__type __type;
2696 };
2697
2698 // Helper to determine the index set for the first tuple-like
2699 // type of a given set.
2700 template<typename...>
2701 struct __make_1st_indices;
2702
2703 template<>
2704 struct __make_1st_indices<>
2705 {
2706 typedef _Index_tuple<> __type;
2707 };
2708
2709 template<typename _Tp, typename... _Tpls>
2710 struct __make_1st_indices<_Tp, _Tpls...>
2711 {
2712 typedef typename _Build_index_tuple<tuple_size<
2713 typename remove_reference<_Tp>::type>::value>::__type __type;
2714 };
2715
2716 // Performs the actual concatenation by step-wise expanding tuple-like
2717 // objects into the elements, which are finally forwarded into the
2718 // result tuple.
2719 template<typename _Ret, typename _Indices, typename... _Tpls>
2720 struct __tuple_concater;
2721
2722 template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2723 struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2724 {
2725 template<typename... _Us>
2726 static constexpr _Ret
2727 _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2728 {
2729 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2730 typedef __tuple_concater<_Ret, __idx, _Tpls...> __next;
2731 return __next::_S_do(std::forward<_Tpls>(__tps)...,
2732 std::forward<_Us>(__us)...,
2733 std::get<_Is>(std::forward<_Tp>(__tp))...);
2734 }
2735 };
2736
2737 template<typename _Ret>
2738 struct __tuple_concater<_Ret, _Index_tuple<>>
2739 {
2740 template<typename... _Us>
2741 static constexpr _Ret
2742 _S_do(_Us&&... __us)
2743 {
2744 return _Ret(std::forward<_Us>(__us)...);
2745 }
2746 };
2747
2748 template<typename... _Tps>
2749 struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2750 { };
2751 /// @endcond
2752
2753 /// Create a `tuple` containing all elements from multiple tuple-like objects
2754#if __cpp_lib_tuple_like // >= C++23
2755 template<__tuple_like... _Tpls>
2756#else
2757 template<typename... _Tpls, typename = typename
2758 enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2759#endif
2760 constexpr auto
2761 tuple_cat(_Tpls&&... __tpls)
2762 -> typename __tuple_cat_result<_Tpls...>::__type
2763 {
2764 typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2765 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2766 typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2767 return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2768 }
2769
2770 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2771 // 2301. Why is tie not constexpr?
2772 /// Return a tuple of lvalue references bound to the arguments
2773 template<typename... _Elements>
2774 constexpr tuple<_Elements&...>
2775 tie(_Elements&... __args) noexcept
2776 { return tuple<_Elements&...>(__args...); }
2777
2778 /// Exchange the values of two tuples
2779 template<typename... _Elements>
2780 _GLIBCXX20_CONSTEXPR
2781 inline
2782#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2783 // Constrained free swap overload, see p0185r1
2784 typename enable_if<__and_<__is_swappable<_Elements>...>::value
2785 >::type
2786#else
2787 void
2788#endif
2790 noexcept(noexcept(__x.swap(__y)))
2791 { __x.swap(__y); }
2792
2793#if __cpp_lib_ranges_zip // >= C++23
2794 template<typename... _Elements>
2795 requires (is_swappable_v<const _Elements> && ...)
2796 constexpr void
2797 swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2798 noexcept(noexcept(__x.swap(__y)))
2799 { __x.swap(__y); }
2800#endif // C++23
2801
2802#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2803 /// Exchange the values of two const tuples (if const elements can be swapped)
2804 template<typename... _Elements>
2805 _GLIBCXX20_CONSTEXPR
2806 typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2807 swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2808#endif
2809
2810 // A class (and instance) which can be used in 'tie' when an element
2811 // of a tuple is not required.
2812 // _GLIBCXX14_CONSTEXPR
2813 // 2933. PR for LWG 2773 could be clearer
2814 struct _Swallow_assign
2815 {
2816 template<class _Tp>
2817 _GLIBCXX14_CONSTEXPR const _Swallow_assign&
2818 operator=(const _Tp&) const
2819 { return *this; }
2820 };
2821
2822 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2823 // 2773. Making std::ignore constexpr
2824 /** Used with `std::tie` to ignore an element of a tuple
2825 *
2826 * When using `std::tie` to assign the elements of a tuple to variables,
2827 * unwanted elements can be ignored by using `std::ignore`. For example:
2828 *
2829 * ```
2830 * int x, y;
2831 * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3);
2832 * ```
2833 *
2834 * This assignment will perform `x=1; std::ignore=2; y=3;` which results
2835 * in the second element being ignored.
2836 *
2837 * @since C++11
2838 */
2839 _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{};
2840
2841 /// Partial specialization for tuples
2842 template<typename... _Types, typename _Alloc>
2843 struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2844
2845 // See stl_pair.h...
2846 /** "piecewise construction" using a tuple of arguments for each member.
2847 *
2848 * @param __first Arguments for the first member of the pair.
2849 * @param __second Arguments for the second member of the pair.
2850 *
2851 * The elements of each tuple will be used as the constructor arguments
2852 * for the data members of the pair.
2853 */
2854 template<class _T1, class _T2>
2855 template<typename... _Args1, typename... _Args2>
2856 _GLIBCXX20_CONSTEXPR
2857 inline
2860 tuple<_Args1...> __first, tuple<_Args2...> __second)
2861 : pair(__first, __second,
2862 typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2863 typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2864 { }
2865
2866 template<class _T1, class _T2>
2867 template<typename... _Args1, size_t... _Indexes1,
2868 typename... _Args2, size_t... _Indexes2>
2869 _GLIBCXX20_CONSTEXPR inline
2871 pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2872 _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2873 : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2874 second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2875 { }
2876
2877#if defined(__cpp_lib_apply) || defined(__cpp_lib_make_from_tuple) // C++ >= 17
2878 // Unpack a std::tuple into a type trait and use its value.
2879 // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2880 // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2881 // Otherwise the result is false (because we don't know if std::get throws).
2882 template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2883 inline constexpr bool __unpack_std_tuple = false;
2884
2885 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2886 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2887 = _Trait<_Tp, _Up...>::value;
2888
2889 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2890 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2891 = _Trait<_Tp, _Up&...>::value;
2892
2893 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2894 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2895 = _Trait<_Tp, const _Up...>::value;
2896
2897 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2898 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2899 = _Trait<_Tp, const _Up&...>::value;
2900#endif
2901
2902#ifdef __cpp_lib_apply // C++ >= 17
2903 template <typename _Fn, typename _Tuple, size_t... _Idx>
2904 constexpr decltype(auto)
2905 __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2906 {
2907 return std::__invoke(std::forward<_Fn>(__f),
2908 std::get<_Idx>(std::forward<_Tuple>(__t))...);
2909 }
2910
2911#if __cpp_lib_tuple_like // >= C++23
2912 template <typename _Fn, __tuple_like _Tuple>
2913#else
2914 template <typename _Fn, typename _Tuple>
2915#endif
2916 constexpr decltype(auto)
2917 apply(_Fn&& __f, _Tuple&& __t)
2918 noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2919 {
2920 using _Indices
2921 = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2922 return std::__apply_impl(std::forward<_Fn>(__f),
2923 std::forward<_Tuple>(__t),
2924 _Indices{});
2925 }
2926#endif
2927
2928#ifdef __cpp_lib_make_from_tuple // C++ >= 17
2929 template <typename _Tp, typename _Tuple, size_t... _Idx>
2930 constexpr _Tp
2931 __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
2932 { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
2933
2934#if __cpp_lib_tuple_like // >= C++23
2935 template <typename _Tp, __tuple_like _Tuple>
2936#else
2937 template <typename _Tp, typename _Tuple>
2938#endif
2939 constexpr _Tp
2940 make_from_tuple(_Tuple&& __t)
2941 noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
2942 {
2943 constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
2944#if __has_builtin(__reference_constructs_from_temporary)
2945 if constexpr (__n == 1)
2946 {
2947 using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
2948 static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
2949 }
2950#endif
2951 return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
2952 make_index_sequence<__n>{});
2953 }
2954#endif
2955
2956#if __cpp_lib_tuple_like // >= C++23
2957 template<__tuple_like _TTuple, __tuple_like _UTuple,
2958 template<typename> class _TQual, template<typename> class _UQual,
2959 typename = make_index_sequence<tuple_size_v<_TTuple>>>
2960 struct __tuple_like_common_reference;
2961
2962 template<__tuple_like _TTuple, __tuple_like _UTuple,
2963 template<typename> class _TQual, template<typename> class _UQual,
2964 size_t... _Is>
2965 requires requires
2966 { typename tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2967 _UQual<tuple_element_t<_Is, _UTuple>>>...>; }
2968 struct __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual, index_sequence<_Is...>>
2969 {
2970 using type = tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2971 _UQual<tuple_element_t<_Is, _UTuple>>>...>;
2972 };
2973
2974 template<__tuple_like _TTuple, __tuple_like _UTuple,
2975 template<typename> class _TQual, template<typename> class _UQual>
2976 requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
2977 && is_same_v<_TTuple, decay_t<_TTuple>>
2978 && is_same_v<_UTuple, decay_t<_UTuple>>
2979 && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
2980 && requires { typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type; }
2981 struct basic_common_reference<_TTuple, _UTuple, _TQual, _UQual>
2982 {
2983 using type = typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type;
2984 };
2985
2986 template<__tuple_like _TTuple, __tuple_like _UTuple,
2987 typename = make_index_sequence<tuple_size_v<_TTuple>>>
2988 struct __tuple_like_common_type;
2989
2990 template<__tuple_like _TTuple, __tuple_like _UTuple, size_t... _Is>
2991 requires requires
2992 { typename tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
2993 tuple_element_t<_Is, _UTuple>>...>; }
2994 struct __tuple_like_common_type<_TTuple, _UTuple, index_sequence<_Is...>>
2995 {
2996 using type = tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
2997 tuple_element_t<_Is, _UTuple>>...>;
2998 };
2999
3000 template<__tuple_like _TTuple, __tuple_like _UTuple>
3001 requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
3002 && is_same_v<_TTuple, decay_t<_TTuple>>
3003 && is_same_v<_UTuple, decay_t<_UTuple>>
3004 && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
3005 && requires { typename __tuple_like_common_type<_TTuple, _UTuple>::type; }
3006 struct common_type<_TTuple, _UTuple>
3007 {
3008 using type = typename __tuple_like_common_type<_TTuple, _UTuple>::type;
3009 };
3010#endif // C++23
3011
3012 /// @}
3013
3014#undef __glibcxx_no_dangling_refs
3015
3016_GLIBCXX_END_NAMESPACE_VERSION
3017} // namespace std
3018
3019#endif // C++11
3020
3021#endif // _GLIBCXX_TUPLE
constexpr bool operator<=(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:855
constexpr bool operator>=(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:869
constexpr bool operator<(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:822
constexpr bool operator>(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:862
__bool_constant< true > true_type
The type used as a compile-time boolean with true value.
Definition type_traits:111
__bool_constant< false > false_type
The type used as a compile-time boolean with false value.
Definition type_traits:114
constexpr auto tuple_cat(_Tpls &&... __tpls) -> typename __tuple_cat_result< _Tpls... >::__type
Create a tuple containing all elements from multiple tuple-like objects.
Definition tuple:2761
constexpr tuple< _Elements &&... > forward_as_tuple(_Elements &&... __args) noexcept
Create a tuple of lvalue or rvalue references to the arguments.
Definition tuple:2636
constexpr tuple< typename __decay_and_strip< _Elements >::__type... > make_tuple(_Elements &&... __args)
Create a tuple containing copies of the arguments.
Definition tuple:2624
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition move.h:126
constexpr _Swallow_assign ignore
Definition tuple:2839
constexpr __invoke_result< _Callable, _Args... >::type __invoke(_Callable &&__fn, _Args &&... __args) noexcept(__is_nothrow_invocable< _Callable, _Args... >::value)
Invoke a callable object.
Definition invoke.h:90
constexpr tuple< _Elements &... > tie(_Elements &... __args) noexcept
Return a tuple of lvalue references bound to the arguments.
Definition tuple:2775
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
Definition move.h:70
ISO C++ entities toplevel namespace is std.
make_integer_sequence< size_t, _Num > make_index_sequence
Alias template make_index_sequence.
Definition utility.h:186
integer_sequence< size_t, _Idx... > index_sequence
Alias template index_sequence.
Definition utility.h:182
make_index_sequence< sizeof...(_Types)> index_sequence_for
Alias template index_sequence_for.
Definition utility.h:190
Primary class template, tuple.
Definition tuple:835
integral_constant
Definition type_traits:88
is_constructible
Definition type_traits:1117
is_nothrow_constructible
Definition type_traits:1185
is_nothrow_default_constructible
Definition type_traits:1194
is_assignable
Definition type_traits:1226
is_nothrow_assignable
Definition type_traits:1260
is_convertible
Definition type_traits:1536
Declare uses_allocator so it can be specialized in <queue> etc.
Definition memoryfwd.h:73
Struct holding two objects of arbitrary type.
Definition stl_pair.h:286
constexpr pair()
Definition stl_pair.h:725
Tag type for piecewise construction of std::pair objects.
Definition stl_pair.h:79
Finds the size of a given tuple type.
Definition utility.h:49
Gives the type of the ith element of a given tuple type.
Definition utility.h:80