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