libstdc++
tuple
Go to the documentation of this file.
1// <tuple> -*- C++ -*-
2
3// Copyright (C) 2007-2025 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 constexpr explicit(!__convertible<const _Elements&...>())
970 tuple(const _Elements&... __elements)
971 noexcept(__nothrow_constructible<const _Elements&...>())
972 requires (__constructible<const _Elements&...>())
973 : _Inherited(__elements...)
974 { }
975
976 template<typename... _UTypes>
977 requires (__disambiguating_constraint<_UTypes...>())
978 && (__constructible<_UTypes...>())
979 && (!__dangles<_UTypes...>())
980 constexpr explicit(!__convertible<_UTypes...>())
981 tuple(_UTypes&&... __u)
982 noexcept(__nothrow_constructible<_UTypes...>())
983 : _Inherited(std::forward<_UTypes>(__u)...)
984 { }
985
986 template<typename... _UTypes>
987 requires (__disambiguating_constraint<_UTypes...>())
988 && (__constructible<_UTypes...>())
989 && (__dangles<_UTypes...>())
990 tuple(_UTypes&&...) = delete;
991
992 constexpr tuple(const tuple&) = default;
993
994 constexpr tuple(tuple&&) = default;
995
996 template<typename... _UTypes>
997 requires (__constructible<const _UTypes&...>())
998 && (!__use_other_ctor<const tuple<_UTypes...>&>())
999 && (!__dangles<const _UTypes&...>())
1000 constexpr explicit(!__convertible<const _UTypes&...>())
1001 tuple(const tuple<_UTypes...>& __u)
1002 noexcept(__nothrow_constructible<const _UTypes&...>())
1003 : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1004 { }
1005
1006 template<typename... _UTypes>
1007 requires (__constructible<const _UTypes&...>())
1008 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1009 && (__dangles<const _UTypes&...>())
1010 tuple(const tuple<_UTypes...>&) = delete;
1011
1012 template<typename... _UTypes>
1013 requires (__constructible<_UTypes...>())
1014 && (!__use_other_ctor<tuple<_UTypes...>>())
1015 && (!__dangles<_UTypes...>())
1016 constexpr explicit(!__convertible<_UTypes...>())
1018 noexcept(__nothrow_constructible<_UTypes...>())
1019 : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1020 { }
1021
1022 template<typename... _UTypes>
1023 requires (__constructible<_UTypes...>())
1024 && (!__use_other_ctor<tuple<_UTypes...>>())
1025 && (__dangles<_UTypes...>())
1026 tuple(tuple<_UTypes...>&&) = delete;
1027
1028#if __cpp_lib_ranges_zip // >= C++23
1029 template<typename... _UTypes>
1030 requires (__constructible<_UTypes&...>())
1031 && (!__use_other_ctor<tuple<_UTypes...>&>())
1032 && (!__dangles<_UTypes&...>())
1033 constexpr explicit(!__convertible<_UTypes&...>())
1035 noexcept(__nothrow_constructible<_UTypes&...>())
1036 : _Inherited(static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1037 { }
1038
1039 template<typename... _UTypes>
1040 requires (__constructible<_UTypes&...>())
1041 && (!__use_other_ctor<tuple<_UTypes...>&>())
1042 && (__dangles<_UTypes&...>())
1043 tuple(tuple<_UTypes...>&) = delete;
1044
1045 template<typename... _UTypes>
1046 requires (__constructible<const _UTypes...>())
1047 && (!__use_other_ctor<const tuple<_UTypes...>>())
1048 && (!__dangles<const _UTypes...>())
1049 constexpr explicit(!__convertible<const _UTypes...>())
1050 tuple(const tuple<_UTypes...>&& __u)
1051 noexcept(__nothrow_constructible<const _UTypes...>())
1052 : _Inherited(static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1053 { }
1054
1055 template<typename... _UTypes>
1056 requires (__constructible<const _UTypes...>())
1057 && (!__use_other_ctor<const tuple<_UTypes...>>())
1058 && (__dangles<const _UTypes...>())
1059 tuple(const tuple<_UTypes...>&&) = delete;
1060#endif // C++23
1061
1062 template<typename _U1, typename _U2>
1063 requires (sizeof...(_Elements) == 2)
1064 && (__constructible<const _U1&, const _U2&>())
1065 && (!__dangles<const _U1&, const _U2&>())
1066 constexpr explicit(!__convertible<const _U1&, const _U2&>())
1067 tuple(const pair<_U1, _U2>& __u)
1068 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1069 : _Inherited(__u.first, __u.second)
1070 { }
1071
1072 template<typename _U1, typename _U2>
1073 requires (sizeof...(_Elements) == 2)
1074 && (__constructible<const _U1&, const _U2&>())
1075 && (__dangles<const _U1&, const _U2&>())
1076 tuple(const pair<_U1, _U2>&) = delete;
1077
1078 template<typename _U1, typename _U2>
1079 requires (sizeof...(_Elements) == 2)
1080 && (__constructible<_U1, _U2>())
1081 && (!__dangles<_U1, _U2>())
1082 constexpr explicit(!__convertible<_U1, _U2>())
1083 tuple(pair<_U1, _U2>&& __u)
1084 noexcept(__nothrow_constructible<_U1, _U2>())
1085 : _Inherited(std::forward<_U1>(__u.first),
1086 std::forward<_U2>(__u.second))
1087 { }
1088
1089 template<typename _U1, typename _U2>
1090 requires (sizeof...(_Elements) == 2)
1091 && (__constructible<_U1, _U2>())
1092 && (__dangles<_U1, _U2>())
1093 tuple(pair<_U1, _U2>&&) = delete;
1094
1095#if __cpp_lib_ranges_zip // >= C++23
1096 template<typename _U1, typename _U2>
1097 requires (sizeof...(_Elements) == 2)
1098 && (__constructible<_U1&, _U2&>())
1099 && (!__dangles<_U1&, _U2&>())
1100 constexpr explicit(!__convertible<_U1&, _U2&>())
1101 tuple(pair<_U1, _U2>& __u)
1102 noexcept(__nothrow_constructible<_U1&, _U2&>())
1103 : _Inherited(__u.first, __u.second)
1104 { }
1105
1106 template<typename _U1, typename _U2>
1107 requires (sizeof...(_Elements) == 2)
1108 && (__constructible<_U1&, _U2&>())
1109 && (__dangles<_U1&, _U2&>())
1110 tuple(pair<_U1, _U2>&) = delete;
1111
1112 template<typename _U1, typename _U2>
1113 requires (sizeof...(_Elements) == 2)
1114 && (__constructible<const _U1, const _U2>())
1115 && (!__dangles<const _U1, const _U2>())
1116 constexpr explicit(!__convertible<const _U1, const _U2>())
1117 tuple(const pair<_U1, _U2>&& __u)
1118 noexcept(__nothrow_constructible<const _U1, const _U2>())
1119 : _Inherited(std::forward<const _U1>(__u.first),
1120 std::forward<const _U2>(__u.second))
1121 { }
1122
1123 template<typename _U1, typename _U2>
1124 requires (sizeof...(_Elements) == 2)
1125 && (__constructible<const _U1, const _U2>())
1126 && (__dangles<const _U1, const _U2>())
1127 tuple(const pair<_U1, _U2>&&) = delete;
1128#endif // C++23
1129
1130#if __cpp_lib_tuple_like // >= C++23
1131 template<__eligible_tuple_like<tuple> _UTuple>
1132 requires (__constructible_from_tuple_like<_UTuple>())
1133 && (!__use_other_ctor<_UTuple>())
1134 && (!__dangles_from_tuple_like<_UTuple>())
1135 constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
1136 tuple(_UTuple&& __u)
1137 : _Inherited(__tuple_like_tag_t{},
1138 std::forward<_UTuple>(__u),
1139 index_sequence_for<_Elements...>{})
1140 { }
1141
1142 template<__eligible_tuple_like<tuple> _UTuple>
1143 requires (__constructible_from_tuple_like<_UTuple>())
1144 && (!__use_other_ctor<_UTuple>())
1145 && (__dangles_from_tuple_like<_UTuple>())
1146 tuple(_UTuple&&) = delete;
1147#endif // C++23
1148
1149 // Allocator-extended constructors.
1150
1151 template<typename _Alloc>
1152 constexpr
1153 explicit(!(__is_implicitly_default_constructible_v<_Elements> && ...))
1154 tuple(allocator_arg_t __tag, const _Alloc& __a)
1155 requires (is_default_constructible_v<_Elements> && ...)
1156 : _Inherited(__tag, __a)
1157 { }
1158
1159 template<typename _Alloc>
1160 constexpr explicit(!__convertible<const _Elements&...>())
1161 tuple(allocator_arg_t __tag, const _Alloc& __a,
1162 const _Elements&... __elements)
1163 requires (__constructible<const _Elements&...>())
1164 : _Inherited(__tag, __a, __elements...)
1165 { }
1166
1167 template<typename _Alloc, typename... _UTypes>
1168 requires (__disambiguating_constraint<_UTypes...>())
1169 && (__constructible<_UTypes...>())
1170 && (!__dangles<_UTypes...>())
1171 constexpr explicit(!__convertible<_UTypes...>())
1172 tuple(allocator_arg_t __tag, const _Alloc& __a, _UTypes&&... __u)
1173 : _Inherited(__tag, __a, std::forward<_UTypes>(__u)...)
1174 { }
1175
1176 template<typename _Alloc, typename... _UTypes>
1177 requires (__disambiguating_constraint<_UTypes...>())
1178 && (__constructible<_UTypes...>())
1179 && (__dangles<_UTypes...>())
1180 tuple(allocator_arg_t, const _Alloc&, _UTypes&&...) = delete;
1181
1182 template<typename _Alloc>
1183 constexpr
1184 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __u)
1185 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__u))
1186 { }
1187
1188 template<typename _Alloc>
1189 requires (__constructible<_Elements...>())
1190 constexpr
1191 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __u)
1192 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__u))
1193 { }
1194
1195 template<typename _Alloc, typename... _UTypes>
1196 requires (__constructible<const _UTypes&...>())
1197 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1198 && (!__dangles<const _UTypes&...>())
1199 constexpr explicit(!__convertible<const _UTypes&...>())
1200 tuple(allocator_arg_t __tag, const _Alloc& __a,
1201 const tuple<_UTypes...>& __u)
1202 : _Inherited(__tag, __a,
1203 static_cast<const _Tuple_impl<0, _UTypes...>&>(__u))
1204 { }
1205
1206 template<typename _Alloc, typename... _UTypes>
1207 requires (__constructible<const _UTypes&...>())
1208 && (!__use_other_ctor<const tuple<_UTypes...>&>())
1209 && (__dangles<const _UTypes&...>())
1210 tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&) = delete;
1211
1212 template<typename _Alloc, typename... _UTypes>
1213 requires (__constructible<_UTypes...>())
1214 && (!__use_other_ctor<tuple<_UTypes...>>())
1215 && (!__dangles<_UTypes...>())
1216 constexpr explicit(!__use_other_ctor<tuple<_UTypes...>>())
1217 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>&& __u)
1218 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&&>(__u))
1219 { }
1220
1221 template<typename _Alloc, typename... _UTypes>
1222 requires (__constructible<_UTypes...>())
1223 && (!__use_other_ctor<tuple<_UTypes...>>())
1224 && (__dangles<_UTypes...>())
1225 tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&&) = delete;
1226
1227#if __cpp_lib_ranges_zip // >= C++23
1228 template<typename _Alloc, typename... _UTypes>
1229 requires (__constructible<_UTypes&...>())
1230 && (!__use_other_ctor<tuple<_UTypes...>&>())
1231 && (!__dangles<_UTypes&...>())
1232 constexpr explicit(!__convertible<_UTypes&...>())
1233 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_UTypes...>& __u)
1234 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _UTypes...>&>(__u))
1235 { }
1236
1237 template<typename _Alloc, typename... _UTypes>
1238 requires (__constructible<_UTypes&...>())
1239 && (!__use_other_ctor<tuple<_UTypes...>&>())
1240 && (__dangles<_UTypes&...>())
1241 tuple(allocator_arg_t, const _Alloc&, tuple<_UTypes...>&) = delete;
1242
1243 template<typename _Alloc, typename... _UTypes>
1244 requires (__constructible<const _UTypes...>())
1245 && (!__use_other_ctor<const tuple<_UTypes...>>())
1246 && (!__dangles<const _UTypes...>())
1247 constexpr explicit(!__convertible<const _UTypes...>())
1248 tuple(allocator_arg_t __tag, const _Alloc& __a,
1249 const tuple<_UTypes...>&& __u)
1250 : _Inherited(__tag, __a,
1251 static_cast<const _Tuple_impl<0, _UTypes...>&&>(__u))
1252 { }
1253
1254 template<typename _Alloc, typename... _UTypes>
1255 requires (__constructible<const _UTypes...>())
1256 && (!__use_other_ctor<const tuple<_UTypes...>>())
1257 && (__dangles<const _UTypes...>())
1258 tuple(allocator_arg_t, const _Alloc&, const tuple<_UTypes...>&&) = delete;
1259#endif // C++23
1260
1261 template<typename _Alloc, typename _U1, typename _U2>
1262 requires (sizeof...(_Elements) == 2)
1263 && (__constructible<const _U1&, const _U2&>())
1264 && (!__dangles<const _U1&, const _U2&>())
1265 constexpr explicit(!__convertible<const _U1&, const _U2&>())
1266 tuple(allocator_arg_t __tag, const _Alloc& __a,
1267 const pair<_U1, _U2>& __u)
1268 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1269 : _Inherited(__tag, __a, __u.first, __u.second)
1270 { }
1271
1272 template<typename _Alloc, typename _U1, typename _U2>
1273 requires (sizeof...(_Elements) == 2)
1274 && (__constructible<const _U1&, const _U2&>())
1275 && (__dangles<const _U1&, const _U2&>())
1276 tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&) = delete;
1277
1278 template<typename _Alloc, typename _U1, typename _U2>
1279 requires (sizeof...(_Elements) == 2)
1280 && (__constructible<_U1, _U2>())
1281 && (!__dangles<_U1, _U2>())
1282 constexpr explicit(!__convertible<_U1, _U2>())
1283 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __u)
1284 noexcept(__nothrow_constructible<_U1, _U2>())
1285 : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1286 { }
1287
1288 template<typename _Alloc, typename _U1, typename _U2>
1289 requires (sizeof...(_Elements) == 2)
1290 && (__constructible<_U1, _U2>())
1291 && (__dangles<_U1, _U2>())
1292 tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&) = delete;
1293
1294#if __cpp_lib_ranges_zip // >= C++23
1295 template<typename _Alloc, typename _U1, typename _U2>
1296 requires (sizeof...(_Elements) == 2)
1297 && (__constructible<_U1&, _U2&>())
1298 && (!__dangles<_U1&, _U2&>())
1299 constexpr explicit(!__convertible<_U1&, _U2&>())
1300 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>& __u)
1301 noexcept(__nothrow_constructible<_U1&, _U2&>())
1302 : _Inherited(__tag, __a, __u.first, __u.second)
1303 { }
1304
1305 template<typename _Alloc, typename _U1, typename _U2>
1306 requires (sizeof...(_Elements) == 2)
1307 && (__constructible<_U1&, _U2&>())
1308 && (__dangles<_U1&, _U2&>())
1309 tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&) = delete;
1310
1311 template<typename _Alloc, typename _U1, typename _U2>
1312 requires (sizeof...(_Elements) == 2)
1313 && (__constructible<const _U1, const _U2>())
1314 && (!__dangles<const _U1, const _U2>())
1315 constexpr explicit(!__convertible<const _U1, const _U2>())
1316 tuple(allocator_arg_t __tag, const _Alloc& __a,
1317 const pair<_U1, _U2>&& __u)
1318 noexcept(__nothrow_constructible<const _U1, const _U2>())
1319 : _Inherited(__tag, __a, std::move(__u.first), std::move(__u.second))
1320 { }
1321
1322 template<typename _Alloc, typename _U1, typename _U2>
1323 requires (sizeof...(_Elements) == 2)
1324 && (__constructible<const _U1, const _U2>())
1325 && (__dangles<const _U1, const _U2>())
1326 tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&&) = delete;
1327#endif // C++23
1328
1329#if __cpp_lib_tuple_like // >= C++23
1330 template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
1331 requires (__constructible_from_tuple_like<_UTuple>())
1332 && (!__use_other_ctor<_UTuple>())
1333 && (!__dangles_from_tuple_like<_UTuple>())
1334 constexpr explicit(!__convertible_from_tuple_like<_UTuple>())
1335 tuple(allocator_arg_t __tag, const _Alloc& __a, _UTuple&& __u)
1336 : _Inherited(__tuple_like_tag_t{},
1337 __tag, __a, std::forward<_UTuple>(__u),
1338 index_sequence_for<_Elements...>{})
1339 { }
1340
1341 template<typename _Alloc, __eligible_tuple_like<tuple> _UTuple>
1342 requires (__constructible_from_tuple_like<_UTuple>())
1343 && (!__use_other_ctor<_UTuple>())
1344 && (__dangles_from_tuple_like<_UTuple>())
1345 tuple(allocator_arg_t, const _Alloc&, _UTuple&&) = delete;
1346#endif // C++23
1347
1348#else // !(concepts && conditional_explicit)
1349
1350 template<bool _Cond>
1351 using _TCC = _TupleConstraints<_Cond, _Elements...>;
1352
1353 // Constraint for non-explicit default constructor
1354 template<bool _Dummy>
1355 using _ImplicitDefaultCtor = __enable_if_t<
1356 _TCC<_Dummy>::__is_implicitly_default_constructible(),
1357 bool>;
1358
1359 // Constraint for explicit default constructor
1360 template<bool _Dummy>
1361 using _ExplicitDefaultCtor = __enable_if_t<
1362 _TCC<_Dummy>::__is_explicitly_default_constructible(),
1363 bool>;
1364
1365 // Constraint for non-explicit constructors
1366 template<bool _Cond, typename... _Args>
1367 using _ImplicitCtor = __enable_if_t<
1368 _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
1369 bool>;
1370
1371 // Constraint for non-explicit constructors
1372 template<bool _Cond, typename... _Args>
1373 using _ExplicitCtor = __enable_if_t<
1374 _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
1375 bool>;
1376
1377 // Condition for noexcept-specifier of a constructor.
1378 template<typename... _UElements>
1379 static constexpr bool __nothrow_constructible()
1380 {
1381 return
1382 __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
1383 }
1384
1385 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1.
1386 template<typename _Up>
1387 static constexpr bool __valid_args()
1388 {
1389 return sizeof...(_Elements) == 1
1390 && !is_same<tuple, __remove_cvref_t<_Up>>::value;
1391 }
1392
1393 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1.
1394 template<typename, typename, typename... _Tail>
1395 static constexpr bool __valid_args()
1396 { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); }
1397
1398 /* Constraint for constructors with a tuple<UTypes...> parameter ensures
1399 * that the constructor is only viable when it would not interfere with
1400 * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&).
1401 * Such constructors are only viable if:
1402 * either sizeof...(Types) != 1,
1403 * or (when Types... expands to T and UTypes... expands to U)
1404 * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>,
1405 * and is_same_v<T, U> are all false.
1406 */
1407 template<typename _Tuple, typename = tuple,
1408 typename = __remove_cvref_t<_Tuple>>
1409 struct _UseOtherCtor
1410 : false_type
1411 { };
1412 // If TUPLE is convertible to the single element in *this,
1413 // then TUPLE should match tuple(UTypes&&...) instead.
1414 template<typename _Tuple, typename _Tp, typename _Up>
1415 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>>
1416 : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>::type
1417 { };
1418 // If TUPLE and *this each have a single element of the same type,
1419 // then TUPLE should match a copy/move constructor instead.
1420 template<typename _Tuple, typename _Tp>
1421 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>>
1422 : true_type
1423 { };
1424
1425 // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
1426 // and the single element in Types can be initialized from TUPLE,
1427 // or is the same type as tuple_element_t<0, TUPLE>.
1428 template<typename _Tuple>
1429 static constexpr bool __use_other_ctor()
1430 { return _UseOtherCtor<_Tuple>::value; }
1431
1432 /// @cond undocumented
1433#undef __glibcxx_no_dangling_refs
1434#if __has_builtin(__reference_constructs_from_temporary) \
1435 && defined _GLIBCXX_DEBUG
1436 // Error if construction from U... would create a dangling ref.
1437# if __cpp_fold_expressions
1438# define __glibcxx_dangling_refs(U) \
1439 (__reference_constructs_from_temporary(_Elements, U) || ...)
1440# else
1441# define __glibcxx_dangling_refs(U) \
1442 __or_<__bool_constant<__reference_constructs_from_temporary(_Elements, U) \
1443 >...>::value
1444# endif
1445# define __glibcxx_no_dangling_refs(U) \
1446 static_assert(!__glibcxx_dangling_refs(U), \
1447 "std::tuple constructor creates a dangling reference")
1448#else
1449# define __glibcxx_no_dangling_refs(U)
1450#endif
1451 /// @endcond
1452
1453 public:
1454 template<typename _Dummy = void,
1455 _ImplicitDefaultCtor<is_void<_Dummy>::value> = true>
1456 constexpr
1457 tuple()
1458 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1459 : _Inherited() { }
1460
1461 template<typename _Dummy = void,
1462 _ExplicitDefaultCtor<is_void<_Dummy>::value> = false>
1463 explicit constexpr
1464 tuple()
1465 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
1466 : _Inherited() { }
1467
1468 template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1469 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1470 constexpr
1471 tuple(const _Elements&... __elements)
1472 noexcept(__nothrow_constructible<const _Elements&...>())
1473 : _Inherited(__elements...) { }
1474
1475 template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
1476 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1477 explicit constexpr
1478 tuple(const _Elements&... __elements)
1479 noexcept(__nothrow_constructible<const _Elements&...>())
1480 : _Inherited(__elements...) { }
1481
1482 template<typename... _UElements,
1483 bool _Valid = __valid_args<_UElements...>(),
1484 _ImplicitCtor<_Valid, _UElements...> = true>
1485 constexpr
1486 tuple(_UElements&&... __elements)
1487 noexcept(__nothrow_constructible<_UElements...>())
1488 : _Inherited(std::forward<_UElements>(__elements)...)
1489 { __glibcxx_no_dangling_refs(_UElements&&); }
1490
1491 template<typename... _UElements,
1492 bool _Valid = __valid_args<_UElements...>(),
1493 _ExplicitCtor<_Valid, _UElements...> = false>
1494 explicit constexpr
1495 tuple(_UElements&&... __elements)
1496 noexcept(__nothrow_constructible<_UElements...>())
1497 : _Inherited(std::forward<_UElements>(__elements)...)
1498 { __glibcxx_no_dangling_refs(_UElements&&); }
1499
1500 constexpr tuple(const tuple&) = default;
1501
1502 constexpr tuple(tuple&&) = default;
1503
1504 template<typename... _UElements,
1505 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1506 && !__use_other_ctor<const tuple<_UElements...>&>(),
1507 _ImplicitCtor<_Valid, const _UElements&...> = true>
1508 constexpr
1509 tuple(const tuple<_UElements...>& __in)
1510 noexcept(__nothrow_constructible<const _UElements&...>())
1511 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1512 { __glibcxx_no_dangling_refs(const _UElements&); }
1513
1514 template<typename... _UElements,
1515 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1516 && !__use_other_ctor<const tuple<_UElements...>&>(),
1517 _ExplicitCtor<_Valid, const _UElements&...> = false>
1518 explicit constexpr
1519 tuple(const tuple<_UElements...>& __in)
1520 noexcept(__nothrow_constructible<const _UElements&...>())
1521 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1522 { __glibcxx_no_dangling_refs(const _UElements&); }
1523
1524 template<typename... _UElements,
1525 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1526 && !__use_other_ctor<tuple<_UElements...>&&>(),
1527 _ImplicitCtor<_Valid, _UElements...> = true>
1528 constexpr
1530 noexcept(__nothrow_constructible<_UElements...>())
1531 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1532 { __glibcxx_no_dangling_refs(_UElements&&); }
1533
1534 template<typename... _UElements,
1535 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1536 && !__use_other_ctor<tuple<_UElements...>&&>(),
1537 _ExplicitCtor<_Valid, _UElements...> = false>
1538 explicit constexpr
1540 noexcept(__nothrow_constructible<_UElements...>())
1541 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1542 { __glibcxx_no_dangling_refs(_UElements&&); }
1543
1544 // Allocator-extended constructors.
1545
1546 template<typename _Alloc,
1547 _ImplicitDefaultCtor<is_object<_Alloc>::value> = true>
1548 _GLIBCXX20_CONSTEXPR
1549 tuple(allocator_arg_t __tag, const _Alloc& __a)
1550 : _Inherited(__tag, __a) { }
1551
1552 template<typename _Alloc,
1553 _ExplicitDefaultCtor<is_object<_Alloc>::value> = false>
1554 _GLIBCXX20_CONSTEXPR
1555 explicit
1556 tuple(allocator_arg_t __tag, const _Alloc& __a)
1557 : _Inherited(__tag, __a) { }
1558
1559 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1560 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
1561 _GLIBCXX20_CONSTEXPR
1562 tuple(allocator_arg_t __tag, const _Alloc& __a,
1563 const _Elements&... __elements)
1564 : _Inherited(__tag, __a, __elements...) { }
1565
1566 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
1567 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
1568 _GLIBCXX20_CONSTEXPR
1569 explicit
1570 tuple(allocator_arg_t __tag, const _Alloc& __a,
1571 const _Elements&... __elements)
1572 : _Inherited(__tag, __a, __elements...) { }
1573
1574 template<typename _Alloc, typename... _UElements,
1575 bool _Valid = __valid_args<_UElements...>(),
1576 _ImplicitCtor<_Valid, _UElements...> = true>
1577 _GLIBCXX20_CONSTEXPR
1578 tuple(allocator_arg_t __tag, const _Alloc& __a,
1579 _UElements&&... __elements)
1580 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1581 { __glibcxx_no_dangling_refs(_UElements&&); }
1582
1583 template<typename _Alloc, typename... _UElements,
1584 bool _Valid = __valid_args<_UElements...>(),
1585 _ExplicitCtor<_Valid, _UElements...> = false>
1586 _GLIBCXX20_CONSTEXPR
1587 explicit
1588 tuple(allocator_arg_t __tag, const _Alloc& __a,
1589 _UElements&&... __elements)
1590 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1591 { __glibcxx_no_dangling_refs(_UElements&&); }
1592
1593 template<typename _Alloc>
1594 _GLIBCXX20_CONSTEXPR
1595 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1596 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1597
1598 template<typename _Alloc>
1599 _GLIBCXX20_CONSTEXPR
1600 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1601 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1602
1603 template<typename _Alloc, typename... _UElements,
1604 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1605 && !__use_other_ctor<const tuple<_UElements...>&>(),
1606 _ImplicitCtor<_Valid, const _UElements&...> = true>
1607 _GLIBCXX20_CONSTEXPR
1608 tuple(allocator_arg_t __tag, const _Alloc& __a,
1609 const tuple<_UElements...>& __in)
1610 : _Inherited(__tag, __a,
1611 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1612 { __glibcxx_no_dangling_refs(const _UElements&); }
1613
1614 template<typename _Alloc, typename... _UElements,
1615 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1616 && !__use_other_ctor<const tuple<_UElements...>&>(),
1617 _ExplicitCtor<_Valid, const _UElements&...> = false>
1618 _GLIBCXX20_CONSTEXPR
1619 explicit
1620 tuple(allocator_arg_t __tag, const _Alloc& __a,
1621 const tuple<_UElements...>& __in)
1622 : _Inherited(__tag, __a,
1623 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1624 { __glibcxx_no_dangling_refs(const _UElements&); }
1625
1626 template<typename _Alloc, typename... _UElements,
1627 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1628 && !__use_other_ctor<tuple<_UElements...>&&>(),
1629 _ImplicitCtor<_Valid, _UElements...> = true>
1630 _GLIBCXX20_CONSTEXPR
1631 tuple(allocator_arg_t __tag, const _Alloc& __a,
1632 tuple<_UElements...>&& __in)
1633 : _Inherited(__tag, __a,
1634 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1635 { __glibcxx_no_dangling_refs(_UElements&&); }
1636
1637 template<typename _Alloc, typename... _UElements,
1638 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1639 && !__use_other_ctor<tuple<_UElements...>&&>(),
1640 _ExplicitCtor<_Valid, _UElements...> = false>
1641 _GLIBCXX20_CONSTEXPR
1642 explicit
1643 tuple(allocator_arg_t __tag, const _Alloc& __a,
1644 tuple<_UElements...>&& __in)
1645 : _Inherited(__tag, __a,
1646 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1647 { __glibcxx_no_dangling_refs(_UElements&&); }
1648#endif // concepts && conditional_explicit
1649
1650 // tuple assignment
1651
1652#if __cpp_concepts && __cpp_consteval // >= C++20
1653 private:
1654 template<typename... _UTypes>
1655 static consteval bool
1656 __assignable()
1657 {
1658 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1659 return __and_v<is_assignable<_Elements&, _UTypes>...>;
1660 else
1661 return false;
1662 }
1663
1664 template<typename... _UTypes>
1665 static consteval bool
1666 __nothrow_assignable()
1667 {
1668 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1670 else
1671 return false;
1672 }
1673
1674#if __cpp_lib_ranges_zip // >= C++23
1675 template<typename... _UTypes>
1676 static consteval bool
1677 __const_assignable()
1678 {
1679 if constexpr (sizeof...(_UTypes) == sizeof...(_Elements))
1681 else
1682 return false;
1683 }
1684#endif // C++23
1685
1686#if __cpp_lib_tuple_like // >= C++23
1687 template<typename _UTuple>
1688 static consteval bool
1689 __assignable_from_tuple_like()
1690 {
1691 return []<size_t... _Is>(index_sequence<_Is...>) {
1692 return __assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1693 }(index_sequence_for<_Elements...>{});
1694 }
1695
1696 template<typename _UTuple>
1697 static consteval bool
1698 __const_assignable_from_tuple_like()
1699 {
1700 return []<size_t... _Is>(index_sequence<_Is...>) {
1701 return __const_assignable<decltype(std::get<_Is>(std::declval<_UTuple>()))...>();
1702 }(index_sequence_for<_Elements...>{});
1703 }
1704#endif // C++23
1705
1706 public:
1707
1708 tuple& operator=(const tuple& __u) = delete;
1709
1710 constexpr tuple&
1711 operator=(const tuple& __u)
1712 noexcept(__nothrow_assignable<const _Elements&...>())
1713 requires (__assignable<const _Elements&...>())
1714 {
1715 this->_M_assign(__u);
1716 return *this;
1717 }
1718
1719 constexpr tuple&
1720 operator=(tuple&& __u)
1721 noexcept(__nothrow_assignable<_Elements...>())
1722 requires (__assignable<_Elements...>())
1723 {
1724 this->_M_assign(std::move(__u));
1725 return *this;
1726 }
1727
1728 template<typename... _UTypes>
1729 requires (__assignable<const _UTypes&...>())
1730 constexpr tuple&
1731 operator=(const tuple<_UTypes...>& __u)
1732 noexcept(__nothrow_assignable<const _UTypes&...>())
1733 {
1734 this->_M_assign(__u);
1735 return *this;
1736 }
1737
1738 template<typename... _UTypes>
1739 requires (__assignable<_UTypes...>())
1740 constexpr tuple&
1741 operator=(tuple<_UTypes...>&& __u)
1742 noexcept(__nothrow_assignable<_UTypes...>())
1743 {
1744 this->_M_assign(std::move(__u));
1745 return *this;
1746 }
1747
1748#if __cpp_lib_ranges_zip // >= C++23
1749 constexpr const tuple&
1750 operator=(const tuple& __u) const
1751 requires (__const_assignable<const _Elements&...>())
1752 {
1753 this->_M_assign(__u);
1754 return *this;
1755 }
1756
1757 constexpr const tuple&
1758 operator=(tuple&& __u) const
1759 requires (__const_assignable<_Elements...>())
1760 {
1761 this->_M_assign(std::move(__u));
1762 return *this;
1763 }
1764
1765 template<typename... _UTypes>
1766 constexpr const tuple&
1767 operator=(const tuple<_UTypes...>& __u) const
1768 requires (__const_assignable<const _UTypes&...>())
1769 {
1770 this->_M_assign(__u);
1771 return *this;
1772 }
1773
1774 template<typename... _UTypes>
1775 constexpr const tuple&
1776 operator=(tuple<_UTypes...>&& __u) const
1777 requires (__const_assignable<_UTypes...>())
1778 {
1779 this->_M_assign(std::move(__u));
1780 return *this;
1781 }
1782#endif // C++23
1783
1784 template<typename _U1, typename _U2>
1785 requires (__assignable<const _U1&, const _U2&>())
1786 constexpr tuple&
1787 operator=(const pair<_U1, _U2>& __u)
1788 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1789 {
1790 this->_M_head(*this) = __u.first;
1791 this->_M_tail(*this)._M_head(*this) = __u.second;
1792 return *this;
1793 }
1794
1795 template<typename _U1, typename _U2>
1796 requires (__assignable<_U1, _U2>())
1797 constexpr tuple&
1798 operator=(pair<_U1, _U2>&& __u)
1799 noexcept(__nothrow_assignable<_U1, _U2>())
1800 {
1801 this->_M_head(*this) = std::forward<_U1>(__u.first);
1802 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1803 return *this;
1804 }
1805
1806#if __cpp_lib_ranges_zip // >= C++23
1807 template<typename _U1, typename _U2>
1808 requires (__const_assignable<const _U1&, const _U2>())
1809 constexpr const tuple&
1810 operator=(const pair<_U1, _U2>& __u) const
1811 {
1812 this->_M_head(*this) = __u.first;
1813 this->_M_tail(*this)._M_head(*this) = __u.second;
1814 return *this;
1815 }
1816
1817 template<typename _U1, typename _U2>
1818 requires (__const_assignable<_U1, _U2>())
1819 constexpr const tuple&
1820 operator=(pair<_U1, _U2>&& __u) const
1821 {
1822 this->_M_head(*this) = std::forward<_U1>(__u.first);
1823 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__u.second);
1824 return *this;
1825 }
1826#endif // C++23
1827
1828#if __cpp_lib_tuple_like // >= C++23
1829 template<__eligible_tuple_like<tuple> _UTuple>
1830 requires (__assignable_from_tuple_like<_UTuple>())
1831 constexpr tuple&
1832 operator=(_UTuple&& __u)
1833 {
1834 this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1835 return *this;
1836 }
1837
1838 template<__eligible_tuple_like<tuple> _UTuple>
1839 requires (__const_assignable_from_tuple_like<_UTuple>())
1840 constexpr const tuple&
1841 operator=(_UTuple&& __u) const
1842 {
1843 this->_M_assign(__tuple_like_tag_t{}, std::forward<_UTuple>(__u));
1844 return *this;
1845 }
1846
1847 template<__tuple_like _UTuple>
1848 requires (!__is_tuple_v<_UTuple>)
1849 friend constexpr bool
1850 operator== [[nodiscard]] (const tuple& __t, const _UTuple& __u)
1851 {
1852 static_assert(sizeof...(_Elements) == tuple_size_v<_UTuple>,
1853 "tuple objects can only be compared if they have equal sizes.");
1854 return [&]<size_t... _Is>(index_sequence<_Is...>) {
1855 return (bool(std::get<_Is>(__t) == std::get<_Is>(__u))
1856 && ...);
1857 }(index_sequence_for<_Elements...>{});
1858 }
1859
1860 template<__tuple_like _UTuple,
1862 struct __tuple_like_common_comparison_category;
1863
1864 template<__tuple_like _UTuple, size_t... _Is>
1865 requires requires
1866 { typename void_t<__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>; }
1867 struct __tuple_like_common_comparison_category<_UTuple, index_sequence<_Is...>>
1868 {
1869 using type = common_comparison_category_t
1870 <__detail::__synth3way_t<_Elements, tuple_element_t<_Is, _UTuple>>...>;
1871 };
1872
1873 template<__tuple_like _UTuple>
1874 requires (!__is_tuple_v<_UTuple>)
1875 friend constexpr typename __tuple_like_common_comparison_category<_UTuple>::type
1876 operator<=>(const tuple& __t, const _UTuple& __u)
1877 {
1878 using _Cat = typename __tuple_like_common_comparison_category<_UTuple>::type;
1879 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Elements...>());
1880 }
1881#endif // C++23
1882
1883#else // ! (concepts && consteval)
1884
1885 private:
1886 template<typename... _UElements>
1887 static constexpr
1888 __enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
1889 __assignable()
1890 { return __and_<is_assignable<_Elements&, _UElements>...>::value; }
1891
1892 // Condition for noexcept-specifier of an assignment operator.
1893 template<typename... _UElements>
1894 static constexpr bool __nothrow_assignable()
1895 {
1896 return
1897 __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
1898 }
1899
1900 public:
1901
1902 _GLIBCXX20_CONSTEXPR
1903 tuple&
1904 operator=(__conditional_t<__assignable<const _Elements&...>(),
1905 const tuple&,
1906 const __nonesuch&> __in)
1907 noexcept(__nothrow_assignable<const _Elements&...>())
1908 {
1909 this->_M_assign(__in);
1910 return *this;
1911 }
1912
1913 _GLIBCXX20_CONSTEXPR
1914 tuple&
1915 operator=(__conditional_t<__assignable<_Elements...>(),
1916 tuple&&,
1917 __nonesuch&&> __in)
1918 noexcept(__nothrow_assignable<_Elements...>())
1919 {
1920 this->_M_assign(std::move(__in));
1921 return *this;
1922 }
1923
1924 template<typename... _UElements>
1925 _GLIBCXX20_CONSTEXPR
1926 __enable_if_t<__assignable<const _UElements&...>(), tuple&>
1927 operator=(const tuple<_UElements...>& __in)
1928 noexcept(__nothrow_assignable<const _UElements&...>())
1929 {
1930 this->_M_assign(__in);
1931 return *this;
1932 }
1933
1934 template<typename... _UElements>
1935 _GLIBCXX20_CONSTEXPR
1936 __enable_if_t<__assignable<_UElements...>(), tuple&>
1937 operator=(tuple<_UElements...>&& __in)
1938 noexcept(__nothrow_assignable<_UElements...>())
1939 {
1940 this->_M_assign(std::move(__in));
1941 return *this;
1942 }
1943#endif // concepts && consteval
1944
1945 // tuple swap
1946 _GLIBCXX20_CONSTEXPR
1947 void
1948 swap(tuple& __in)
1949 noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
1950 { _Inherited::_M_swap(__in); }
1951
1952#if __cpp_lib_ranges_zip // >= C++23
1953 // As an extension, we constrain the const swap member function in order
1954 // to continue accepting explicit instantiation of tuples whose elements
1955 // are not all const swappable. Without this constraint, such an
1956 // explicit instantiation would also instantiate the ill-formed body of
1957 // this function and yield a hard error. This constraint shouldn't
1958 // affect the behavior of valid programs.
1959 constexpr void
1960 swap(const tuple& __in) const
1961 noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
1962 requires (is_swappable_v<const _Elements> && ...)
1963 { _Inherited::_M_swap(__in); }
1964#endif // C++23
1965 };
1966
1967#if __cpp_deduction_guides >= 201606
1968 template<typename... _UTypes>
1969 tuple(_UTypes...) -> tuple<_UTypes...>;
1970 template<typename _T1, typename _T2>
1972 template<typename _Alloc, typename... _UTypes>
1973 tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
1974 template<typename _Alloc, typename _T1, typename _T2>
1975 tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
1976 template<typename _Alloc, typename... _UTypes>
1977 tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
1978#endif
1979
1980 // Explicit specialization, zero-element tuple.
1981 template<>
1982 class tuple<>
1983 {
1984 public:
1985 _GLIBCXX20_CONSTEXPR
1986 void swap(tuple&) noexcept { /* no-op */ }
1987#if __cpp_lib_ranges_zip // >= C++23
1988 constexpr void swap(const tuple&) const noexcept { /* no-op */ }
1989#endif
1990 // We need the default since we're going to define no-op
1991 // allocator constructors.
1992 tuple() = default;
1993 // No-op allocator constructors.
1994 template<typename _Alloc>
1995 _GLIBCXX20_CONSTEXPR
1996 tuple(allocator_arg_t, const _Alloc&) noexcept { }
1997 template<typename _Alloc>
1998 _GLIBCXX20_CONSTEXPR
1999 tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
2000 };
2001
2002#if !(__cpp_concepts && __cpp_consteval && __cpp_conditional_explicit) // !C++20
2003 /// Partial specialization, 2-element tuple.
2004 /// Includes construction and assignment from a pair.
2005 template<typename _T1, typename _T2>
2006 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
2007 {
2008 typedef _Tuple_impl<0, _T1, _T2> _Inherited;
2009
2010 // Constraint for non-explicit default constructor
2011 template<bool _Dummy, typename _U1, typename _U2>
2012 using _ImplicitDefaultCtor = __enable_if_t<
2013 _TupleConstraints<_Dummy, _U1, _U2>::
2014 __is_implicitly_default_constructible(),
2015 bool>;
2016
2017 // Constraint for explicit default constructor
2018 template<bool _Dummy, typename _U1, typename _U2>
2019 using _ExplicitDefaultCtor = __enable_if_t<
2020 _TupleConstraints<_Dummy, _U1, _U2>::
2021 __is_explicitly_default_constructible(),
2022 bool>;
2023
2024 template<bool _Dummy>
2025 using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
2026
2027 // Constraint for non-explicit constructors
2028 template<bool _Cond, typename _U1, typename _U2>
2029 using _ImplicitCtor = __enable_if_t<
2030 _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
2031 bool>;
2032
2033 // Constraint for non-explicit constructors
2034 template<bool _Cond, typename _U1, typename _U2>
2035 using _ExplicitCtor = __enable_if_t<
2036 _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
2037 bool>;
2038
2039 template<typename _U1, typename _U2>
2040 static constexpr bool __assignable()
2041 {
2042 return __and_<is_assignable<_T1&, _U1>,
2044 }
2045
2046 template<typename _U1, typename _U2>
2047 static constexpr bool __nothrow_assignable()
2048 {
2049 return __and_<is_nothrow_assignable<_T1&, _U1>,
2051 }
2052
2053 template<typename _U1, typename _U2>
2054 static constexpr bool __nothrow_constructible()
2055 {
2056 return __and_<is_nothrow_constructible<_T1, _U1>,
2058 }
2059
2060 static constexpr bool __nothrow_default_constructible()
2061 {
2062 return __and_<is_nothrow_default_constructible<_T1>,
2064 }
2065
2066 template<typename _U1>
2067 static constexpr bool __is_alloc_arg()
2068 { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
2069
2070 /// @cond undocumented
2071#undef __glibcxx_no_dangling_refs
2072 // Error if construction from _U1 and _U2 would create a dangling ref.
2073#if __has_builtin(__reference_constructs_from_temporary) \
2074 && defined _GLIBCXX_DEBUG
2075# define __glibcxx_no_dangling_refs(_U1, _U2) \
2076 static_assert(!__reference_constructs_from_temporary(_T1, _U1) \
2077 && !__reference_constructs_from_temporary(_T2, _U2), \
2078 "std::tuple constructor creates a dangling reference")
2079#else
2080# define __glibcxx_no_dangling_refs(_U1, _U2)
2081#endif
2082 /// @endcond
2083
2084 public:
2085 template<bool _Dummy = true,
2086 _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
2087 constexpr
2088 tuple()
2089 noexcept(__nothrow_default_constructible())
2090 : _Inherited() { }
2091
2092 template<bool _Dummy = true,
2093 _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
2094 explicit constexpr
2095 tuple()
2096 noexcept(__nothrow_default_constructible())
2097 : _Inherited() { }
2098
2099 template<bool _Dummy = true,
2100 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2101 constexpr
2102 tuple(const _T1& __a1, const _T2& __a2)
2103 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2104 : _Inherited(__a1, __a2) { }
2105
2106 template<bool _Dummy = true,
2107 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2108 explicit constexpr
2109 tuple(const _T1& __a1, const _T2& __a2)
2110 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
2111 : _Inherited(__a1, __a2) { }
2112
2113 template<typename _U1, typename _U2,
2114 _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
2115 constexpr
2116 tuple(_U1&& __a1, _U2&& __a2)
2117 noexcept(__nothrow_constructible<_U1, _U2>())
2118 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2119 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2120
2121 template<typename _U1, typename _U2,
2122 _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
2123 explicit constexpr
2124 tuple(_U1&& __a1, _U2&& __a2)
2125 noexcept(__nothrow_constructible<_U1, _U2>())
2126 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2))
2127 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2128
2129 constexpr tuple(const tuple&) = default;
2130
2131 constexpr tuple(tuple&&) = default;
2132
2133 template<typename _U1, typename _U2,
2134 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2135 constexpr
2136 tuple(const tuple<_U1, _U2>& __in)
2137 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2138 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2139 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2140
2141 template<typename _U1, typename _U2,
2142 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2143 explicit constexpr
2144 tuple(const tuple<_U1, _U2>& __in)
2145 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2146 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2147 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2148
2149 template<typename _U1, typename _U2,
2150 _ImplicitCtor<true, _U1, _U2> = true>
2151 constexpr
2152 tuple(tuple<_U1, _U2>&& __in)
2153 noexcept(__nothrow_constructible<_U1, _U2>())
2154 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2155 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2156
2157 template<typename _U1, typename _U2,
2158 _ExplicitCtor<true, _U1, _U2> = false>
2159 explicit constexpr
2160 tuple(tuple<_U1, _U2>&& __in)
2161 noexcept(__nothrow_constructible<_U1, _U2>())
2162 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2163 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2164
2165 template<typename _U1, typename _U2,
2166 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2167 constexpr
2168 tuple(const pair<_U1, _U2>& __in)
2169 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2170 : _Inherited(__in.first, __in.second)
2171 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2172
2173 template<typename _U1, typename _U2,
2174 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2175 explicit constexpr
2176 tuple(const pair<_U1, _U2>& __in)
2177 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
2178 : _Inherited(__in.first, __in.second)
2179 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2180
2181 template<typename _U1, typename _U2,
2182 _ImplicitCtor<true, _U1, _U2> = true>
2183 constexpr
2184 tuple(pair<_U1, _U2>&& __in)
2185 noexcept(__nothrow_constructible<_U1, _U2>())
2186 : _Inherited(std::forward<_U1>(__in.first),
2187 std::forward<_U2>(__in.second))
2188 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2189
2190 template<typename _U1, typename _U2,
2191 _ExplicitCtor<true, _U1, _U2> = false>
2192 explicit constexpr
2193 tuple(pair<_U1, _U2>&& __in)
2194 noexcept(__nothrow_constructible<_U1, _U2>())
2195 : _Inherited(std::forward<_U1>(__in.first),
2196 std::forward<_U2>(__in.second))
2197 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2198
2199 // Allocator-extended constructors.
2200
2201 template<typename _Alloc,
2202 _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
2203 _GLIBCXX20_CONSTEXPR
2204 tuple(allocator_arg_t __tag, const _Alloc& __a)
2205 : _Inherited(__tag, __a) { }
2206
2207 template<typename _Alloc,
2208 _ExplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = false>
2209 _GLIBCXX20_CONSTEXPR
2210 explicit
2211 tuple(allocator_arg_t __tag, const _Alloc& __a)
2212 : _Inherited(__tag, __a) { }
2213
2214 template<typename _Alloc, bool _Dummy = true,
2215 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
2216 _GLIBCXX20_CONSTEXPR
2217 tuple(allocator_arg_t __tag, const _Alloc& __a,
2218 const _T1& __a1, const _T2& __a2)
2219 : _Inherited(__tag, __a, __a1, __a2) { }
2220
2221 template<typename _Alloc, bool _Dummy = true,
2222 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
2223 explicit
2224 _GLIBCXX20_CONSTEXPR
2225 tuple(allocator_arg_t __tag, const _Alloc& __a,
2226 const _T1& __a1, const _T2& __a2)
2227 : _Inherited(__tag, __a, __a1, __a2) { }
2228
2229 template<typename _Alloc, typename _U1, typename _U2,
2230 _ImplicitCtor<true, _U1, _U2> = true>
2231 _GLIBCXX20_CONSTEXPR
2232 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
2233 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2234 std::forward<_U2>(__a2))
2235 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2236
2237 template<typename _Alloc, typename _U1, typename _U2,
2238 _ExplicitCtor<true, _U1, _U2> = false>
2239 explicit
2240 _GLIBCXX20_CONSTEXPR
2241 tuple(allocator_arg_t __tag, const _Alloc& __a,
2242 _U1&& __a1, _U2&& __a2)
2243 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
2244 std::forward<_U2>(__a2))
2245 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2246
2247 template<typename _Alloc>
2248 _GLIBCXX20_CONSTEXPR
2249 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
2250 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
2251
2252 template<typename _Alloc>
2253 _GLIBCXX20_CONSTEXPR
2254 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
2255 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
2256
2257 template<typename _Alloc, typename _U1, typename _U2,
2258 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2259 _GLIBCXX20_CONSTEXPR
2260 tuple(allocator_arg_t __tag, const _Alloc& __a,
2261 const tuple<_U1, _U2>& __in)
2262 : _Inherited(__tag, __a,
2263 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2264 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2265
2266 template<typename _Alloc, typename _U1, typename _U2,
2267 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2268 explicit
2269 _GLIBCXX20_CONSTEXPR
2270 tuple(allocator_arg_t __tag, const _Alloc& __a,
2271 const tuple<_U1, _U2>& __in)
2272 : _Inherited(__tag, __a,
2273 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
2274 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2275
2276 template<typename _Alloc, typename _U1, typename _U2,
2277 _ImplicitCtor<true, _U1, _U2> = true>
2278 _GLIBCXX20_CONSTEXPR
2279 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2280 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2281 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2282
2283 template<typename _Alloc, typename _U1, typename _U2,
2284 _ExplicitCtor<true, _U1, _U2> = false>
2285 explicit
2286 _GLIBCXX20_CONSTEXPR
2287 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
2288 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
2289 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2290
2291 template<typename _Alloc, typename _U1, typename _U2,
2292 _ImplicitCtor<true, const _U1&, const _U2&> = true>
2293 _GLIBCXX20_CONSTEXPR
2294 tuple(allocator_arg_t __tag, const _Alloc& __a,
2295 const pair<_U1, _U2>& __in)
2296 : _Inherited(__tag, __a, __in.first, __in.second)
2297 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2298
2299 template<typename _Alloc, typename _U1, typename _U2,
2300 _ExplicitCtor<true, const _U1&, const _U2&> = false>
2301 explicit
2302 _GLIBCXX20_CONSTEXPR
2303 tuple(allocator_arg_t __tag, const _Alloc& __a,
2304 const pair<_U1, _U2>& __in)
2305 : _Inherited(__tag, __a, __in.first, __in.second)
2306 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); }
2307
2308 template<typename _Alloc, typename _U1, typename _U2,
2309 _ImplicitCtor<true, _U1, _U2> = true>
2310 _GLIBCXX20_CONSTEXPR
2311 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2312 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2313 std::forward<_U2>(__in.second))
2314 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2315
2316 template<typename _Alloc, typename _U1, typename _U2,
2317 _ExplicitCtor<true, _U1, _U2> = false>
2318 explicit
2319 _GLIBCXX20_CONSTEXPR
2320 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
2321 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
2322 std::forward<_U2>(__in.second))
2323 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); }
2324
2325 // Tuple assignment.
2326
2327 _GLIBCXX20_CONSTEXPR
2328 tuple&
2329 operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
2330 const tuple&,
2331 const __nonesuch&> __in)
2332 noexcept(__nothrow_assignable<const _T1&, const _T2&>())
2333 {
2334 this->_M_assign(__in);
2335 return *this;
2336 }
2337
2338 _GLIBCXX20_CONSTEXPR
2339 tuple&
2340 operator=(__conditional_t<__assignable<_T1, _T2>(),
2341 tuple&&,
2342 __nonesuch&&> __in)
2343 noexcept(__nothrow_assignable<_T1, _T2>())
2344 {
2345 this->_M_assign(std::move(__in));
2346 return *this;
2347 }
2348
2349 template<typename _U1, typename _U2>
2350 _GLIBCXX20_CONSTEXPR
2351 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2352 operator=(const tuple<_U1, _U2>& __in)
2353 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2354 {
2355 this->_M_assign(__in);
2356 return *this;
2357 }
2358
2359 template<typename _U1, typename _U2>
2360 _GLIBCXX20_CONSTEXPR
2361 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2362 operator=(tuple<_U1, _U2>&& __in)
2363 noexcept(__nothrow_assignable<_U1, _U2>())
2364 {
2365 this->_M_assign(std::move(__in));
2366 return *this;
2367 }
2368
2369 template<typename _U1, typename _U2>
2370 _GLIBCXX20_CONSTEXPR
2371 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
2372 operator=(const pair<_U1, _U2>& __in)
2373 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
2374 {
2375 this->_M_head(*this) = __in.first;
2376 this->_M_tail(*this)._M_head(*this) = __in.second;
2377 return *this;
2378 }
2379
2380 template<typename _U1, typename _U2>
2381 _GLIBCXX20_CONSTEXPR
2382 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
2383 operator=(pair<_U1, _U2>&& __in)
2384 noexcept(__nothrow_assignable<_U1, _U2>())
2385 {
2386 this->_M_head(*this) = std::forward<_U1>(__in.first);
2387 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
2388 return *this;
2389 }
2390
2391 _GLIBCXX20_CONSTEXPR
2392 void
2393 swap(tuple& __in)
2394 noexcept(__and_<__is_nothrow_swappable<_T1>,
2395 __is_nothrow_swappable<_T2>>::value)
2396 { _Inherited::_M_swap(__in); }
2397 };
2398#endif // concepts && conditional_explicit
2399
2400 /// class tuple_size
2401 template<typename... _Elements>
2402 struct tuple_size<tuple<_Elements...>>
2403 : public integral_constant<size_t, sizeof...(_Elements)> { };
2404
2405#if __cplusplus >= 201703L
2406 template<typename... _Types>
2407 inline constexpr size_t tuple_size_v<tuple<_Types...>>
2408 = sizeof...(_Types);
2409
2410 template<typename... _Types>
2411 inline constexpr size_t tuple_size_v<const tuple<_Types...>>
2412 = sizeof...(_Types);
2413#endif
2414
2415 /// Trait to get the Ith element type from a tuple.
2416 template<size_t __i, typename... _Types>
2417 struct tuple_element<__i, tuple<_Types...>>
2418 {
2419 static_assert(__i < sizeof...(_Types), "tuple index must be in range");
2420
2421 using type = typename _Nth_type<__i, _Types...>::type;
2422 };
2423
2424 template<size_t __i, typename _Head, typename... _Tail>
2425 constexpr _Head&
2426 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2427 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2428
2429 template<size_t __i, typename _Head, typename... _Tail>
2430 constexpr const _Head&
2431 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
2432 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
2433
2434 // Deleted overload to improve diagnostics for invalid indices
2435 template<size_t __i, typename... _Types>
2436 __enable_if_t<(__i >= sizeof...(_Types))>
2437 __get_helper(const tuple<_Types...>&) = delete;
2438
2439 /// Return a reference to the ith element of a tuple.
2440 template<size_t __i, typename... _Elements>
2441 constexpr __tuple_element_t<__i, tuple<_Elements...>>&
2442 get(tuple<_Elements...>& __t) noexcept
2443 { return std::__get_helper<__i>(__t); }
2444
2445 /// Return a const reference to the ith element of a const tuple.
2446 template<size_t __i, typename... _Elements>
2447 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
2448 get(const tuple<_Elements...>& __t) noexcept
2449 { return std::__get_helper<__i>(__t); }
2450
2451 /// Return an rvalue reference to the ith element of a tuple rvalue.
2452 template<size_t __i, typename... _Elements>
2453 constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
2454 get(tuple<_Elements...>&& __t) noexcept
2455 {
2456 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2457 return std::forward<__element_type>(std::__get_helper<__i>(__t));
2458 }
2459
2460 /// Return a const rvalue reference to the ith element of a const tuple rvalue.
2461 template<size_t __i, typename... _Elements>
2462 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
2463 get(const tuple<_Elements...>&& __t) noexcept
2464 {
2465 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
2466 return std::forward<const __element_type>(std::__get_helper<__i>(__t));
2467 }
2468
2469 /// @cond undocumented
2470 // Deleted overload chosen for invalid indices.
2471 template<size_t __i, typename... _Elements>
2472 constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
2473 get(const tuple<_Elements...>&) = delete;
2474 /// @endcond
2475
2476#ifdef __cpp_lib_tuples_by_type // C++ >= 14
2477 /// Return a reference to the unique element of type _Tp of a tuple.
2478 template <typename _Tp, typename... _Types>
2479 constexpr _Tp&
2480 get(tuple<_Types...>& __t) noexcept
2481 {
2482 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2483 static_assert(__idx < sizeof...(_Types),
2484 "the type T in std::get<T> must occur exactly once in the tuple");
2485 return std::__get_helper<__idx>(__t);
2486 }
2487
2488 /// Return a reference to the unique element of type _Tp of a tuple rvalue.
2489 template <typename _Tp, typename... _Types>
2490 constexpr _Tp&&
2491 get(tuple<_Types...>&& __t) noexcept
2492 {
2493 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2494 static_assert(__idx < sizeof...(_Types),
2495 "the type T in std::get<T> must occur exactly once in the tuple");
2496 return std::forward<_Tp>(std::__get_helper<__idx>(__t));
2497 }
2498
2499 /// Return a const reference to the unique element of type _Tp of a tuple.
2500 template <typename _Tp, typename... _Types>
2501 constexpr const _Tp&
2502 get(const tuple<_Types...>& __t) noexcept
2503 {
2504 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2505 static_assert(__idx < sizeof...(_Types),
2506 "the type T in std::get<T> must occur exactly once in the tuple");
2507 return std::__get_helper<__idx>(__t);
2508 }
2509
2510 /// Return a const reference to the unique element of type _Tp of
2511 /// a const tuple rvalue.
2512 template <typename _Tp, typename... _Types>
2513 constexpr const _Tp&&
2514 get(const tuple<_Types...>&& __t) noexcept
2515 {
2516 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
2517 static_assert(__idx < sizeof...(_Types),
2518 "the type T in std::get<T> must occur exactly once in the tuple");
2519 return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
2520 }
2521#endif
2522
2523#if __cpp_lib_three_way_comparison
2524 template<typename... _Tps, typename... _Ups>
2525 requires (sizeof...(_Tps) == sizeof...(_Ups))
2526 && (requires (const _Tps& __t, const _Ups& __u) {
2527 { __t == __u } -> __detail::__boolean_testable;
2528 } && ...)
2529 constexpr bool
2530 operator== [[nodiscard]] (const tuple<_Tps...>& __t,
2531 const tuple<_Ups...>& __u)
2532 {
2533 return [&]<size_t... _Inds>(index_sequence<_Inds...>) {
2534 // Fold == over the tuples until non-equal elements are found.
2535 return ((std::get<_Inds>(__t) == std::get<_Inds>(__u)) && ...);
2536 }(index_sequence_for<_Tps...>{});
2537 }
2538
2539 template<typename _Cat, typename _Tp, typename _Up, typename _IndexSeq>
2540 [[nodiscard]]
2541 constexpr _Cat
2542 __tuple_cmp(const _Tp& __t, const _Up& __u, _IndexSeq __indices)
2543 {
2544 _Cat __c = _Cat::equivalent;
2545
2546 // Set __c to the comparison result of two corresponding elements.
2547 // Return true they are equivalent.
2548 auto __cmp = [&]<size_t _Ind>(integral_constant<size_t, _Ind>) {
2549 __c = __detail::__synth3way(std::get<_Ind>(__t), std::get<_Ind>(__u));
2550 return __c == 0;
2551 };
2552
2553 [&]<size_t... _Inds>(index_sequence<_Inds...>) {
2554 // Fold __cmp over the tuples until non-equivalent elements are found.
2555 (void)(__cmp(integral_constant<size_t, _Inds>{}) && ...);
2556 }(__indices);
2557
2558 return __c;
2559 }
2560
2561 template<typename... _Tps, typename... _Ups>
2562 requires (sizeof...(_Tps) == sizeof...(_Ups))
2563 && (requires { typename __detail::__synth3way_t<_Tps, _Ups>; } && ...)
2564 constexpr
2565 common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
2566 operator<=> [[nodiscard]] (const tuple<_Tps...>& __t,
2567 const tuple<_Ups...>& __u)
2568 {
2569 using _Cat
2570 = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
2571 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
2572 }
2573#else
2574
2575 // This class performs the comparison operations on tuples
2576 template<typename _Tp, typename _Up, size_t __i, size_t __size>
2577 struct __tuple_compare
2578 {
2579 static constexpr bool
2580 __eq(const _Tp& __t, const _Up& __u)
2581 {
2582 return bool(std::get<__i>(__t) == std::get<__i>(__u))
2583 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
2584 }
2585
2586 static constexpr bool
2587 __less(const _Tp& __t, const _Up& __u)
2588 {
2589 return bool(std::get<__i>(__t) < std::get<__i>(__u))
2590 || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
2591 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
2592 }
2593 };
2594
2595 template<typename _Tp, typename _Up, size_t __size>
2596 struct __tuple_compare<_Tp, _Up, __size, __size>
2597 {
2598 static constexpr bool
2599 __eq(const _Tp&, const _Up&) { return true; }
2600
2601 static constexpr bool
2602 __less(const _Tp&, const _Up&) { return false; }
2603 };
2604
2605 template<typename... _TElements, typename... _UElements>
2606 _GLIBCXX_NODISCARD
2607 constexpr bool
2608 operator==(const tuple<_TElements...>& __t,
2609 const tuple<_UElements...>& __u)
2610 {
2611 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2612 "tuple objects can only be compared if they have equal sizes.");
2613 using __compare = __tuple_compare<tuple<_TElements...>,
2614 tuple<_UElements...>,
2615 0, sizeof...(_TElements)>;
2616 return __compare::__eq(__t, __u);
2617 }
2618
2619 template<typename... _TElements, typename... _UElements>
2620 _GLIBCXX_NODISCARD
2621 constexpr bool
2622 operator<(const tuple<_TElements...>& __t,
2623 const tuple<_UElements...>& __u)
2624 {
2625 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
2626 "tuple objects can only be compared if they have equal sizes.");
2627 using __compare = __tuple_compare<tuple<_TElements...>,
2628 tuple<_UElements...>,
2629 0, sizeof...(_TElements)>;
2630 return __compare::__less(__t, __u);
2631 }
2632
2633 template<typename... _TElements, typename... _UElements>
2634 _GLIBCXX_NODISCARD
2635 constexpr bool
2636 operator!=(const tuple<_TElements...>& __t,
2637 const tuple<_UElements...>& __u)
2638 { return !(__t == __u); }
2639
2640 template<typename... _TElements, typename... _UElements>
2641 _GLIBCXX_NODISCARD
2642 constexpr bool
2643 operator>(const tuple<_TElements...>& __t,
2644 const tuple<_UElements...>& __u)
2645 { return __u < __t; }
2646
2647 template<typename... _TElements, typename... _UElements>
2648 _GLIBCXX_NODISCARD
2649 constexpr bool
2650 operator<=(const tuple<_TElements...>& __t,
2651 const tuple<_UElements...>& __u)
2652 { return !(__u < __t); }
2653
2654 template<typename... _TElements, typename... _UElements>
2655 _GLIBCXX_NODISCARD
2656 constexpr bool
2657 operator>=(const tuple<_TElements...>& __t,
2658 const tuple<_UElements...>& __u)
2659 { return !(__t < __u); }
2660#endif // three_way_comparison
2661
2662 // NB: DR 705.
2663 /// Create a tuple containing copies of the arguments
2664 template<typename... _Elements>
2665 constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
2666 make_tuple(_Elements&&... __args)
2667 {
2669 __result_type;
2670 return __result_type(std::forward<_Elements>(__args)...);
2671 }
2672
2673 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2674 // 2275. Why is forward_as_tuple not constexpr?
2675 /// Create a tuple of lvalue or rvalue references to the arguments
2676 template<typename... _Elements>
2677 constexpr tuple<_Elements&&...>
2678 forward_as_tuple(_Elements&&... __args) noexcept
2679 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2680
2681 /// @cond undocumented
2682 template<size_t, typename, typename, size_t>
2683 struct __make_tuple_impl;
2684
2685 template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
2686 struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
2687 : __make_tuple_impl<_Idx + 1,
2688 tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
2689 _Tuple, _Nm>
2690 { };
2691
2692 template<size_t _Nm, typename _Tuple, typename... _Tp>
2693 struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
2694 {
2695 typedef tuple<_Tp...> __type;
2696 };
2697
2698 template<typename _Tuple>
2699 struct __do_make_tuple
2700 : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
2701 { };
2702
2703 // Returns the std::tuple equivalent of a tuple-like type.
2704 template<typename _Tuple>
2705 struct __make_tuple
2706 : public __do_make_tuple<__remove_cvref_t<_Tuple>>
2707 { };
2708
2709 // Combines several std::tuple's into a single one.
2710 template<typename...>
2711 struct __combine_tuples;
2712
2713 template<>
2714 struct __combine_tuples<>
2715 {
2716 typedef tuple<> __type;
2717 };
2718
2719 template<typename... _Ts>
2720 struct __combine_tuples<tuple<_Ts...>>
2721 {
2722 typedef tuple<_Ts...> __type;
2723 };
2724
2725 template<typename... _T1s, typename... _T2s, typename... _Rem>
2726 struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
2727 {
2728 typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
2729 _Rem...>::__type __type;
2730 };
2731
2732 // Computes the result type of tuple_cat given a set of tuple-like types.
2733 template<typename... _Tpls>
2734 struct __tuple_cat_result
2735 {
2736 typedef typename __combine_tuples
2737 <typename __make_tuple<_Tpls>::__type...>::__type __type;
2738 };
2739
2740 // Helper to determine the index set for the first tuple-like
2741 // type of a given set.
2742 template<typename...>
2743 struct __make_1st_indices;
2744
2745 template<>
2746 struct __make_1st_indices<>
2747 {
2748 typedef _Index_tuple<> __type;
2749 };
2750
2751 template<typename _Tp, typename... _Tpls>
2752 struct __make_1st_indices<_Tp, _Tpls...>
2753 {
2754 typedef typename _Build_index_tuple<tuple_size<
2755 typename remove_reference<_Tp>::type>::value>::__type __type;
2756 };
2757
2758 // Performs the actual concatenation by step-wise expanding tuple-like
2759 // objects into the elements, which are finally forwarded into the
2760 // result tuple.
2761 template<typename _Ret, typename _Indices, typename... _Tpls>
2762 struct __tuple_concater;
2763
2764 template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2765 struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2766 {
2767 template<typename... _Us>
2768 static constexpr _Ret
2769 _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2770 {
2771 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2772 typedef __tuple_concater<_Ret, __idx, _Tpls...> __next;
2773 return __next::_S_do(std::forward<_Tpls>(__tps)...,
2774 std::forward<_Us>(__us)...,
2775 std::get<_Is>(std::forward<_Tp>(__tp))...);
2776 }
2777 };
2778
2779 template<typename _Ret>
2780 struct __tuple_concater<_Ret, _Index_tuple<>>
2781 {
2782 template<typename... _Us>
2783 static constexpr _Ret
2784 _S_do(_Us&&... __us)
2785 {
2786 return _Ret(std::forward<_Us>(__us)...);
2787 }
2788 };
2789
2790 template<typename... _Tps>
2791 struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2792 { };
2793 /// @endcond
2794
2795 /// Create a `tuple` containing all elements from multiple tuple-like objects
2796#if __cpp_lib_tuple_like // >= C++23
2797 template<__tuple_like... _Tpls>
2798#else
2799 template<typename... _Tpls, typename = typename
2800 enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2801#endif
2802 constexpr auto
2803 tuple_cat(_Tpls&&... __tpls)
2804 -> typename __tuple_cat_result<_Tpls...>::__type
2805 {
2806 typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2807 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2808 typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2809 return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2810 }
2811
2812 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2813 // 2301. Why is tie not constexpr?
2814 /// Return a tuple of lvalue references bound to the arguments
2815 template<typename... _Elements>
2816 constexpr tuple<_Elements&...>
2817 tie(_Elements&... __args) noexcept
2818 { return tuple<_Elements&...>(__args...); }
2819
2820 /// Exchange the values of two tuples
2821 template<typename... _Elements>
2822 _GLIBCXX20_CONSTEXPR
2823 inline
2824#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2825 // Constrained free swap overload, see p0185r1
2826 typename enable_if<__and_<__is_swappable<_Elements>...>::value
2827 >::type
2828#else
2829 void
2830#endif
2832 noexcept(noexcept(__x.swap(__y)))
2833 { __x.swap(__y); }
2834
2835#if __cpp_lib_ranges_zip // >= C++23
2836 template<typename... _Elements>
2837 requires (is_swappable_v<const _Elements> && ...)
2838 constexpr void
2839 swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2840 noexcept(noexcept(__x.swap(__y)))
2841 { __x.swap(__y); }
2842#endif // C++23
2843
2844#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2845 /// Exchange the values of two const tuples (if const elements can be swapped)
2846 template<typename... _Elements>
2847 _GLIBCXX20_CONSTEXPR
2848 typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2849 swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2850#endif
2851
2852 /// Partial specialization for tuples
2853 template<typename... _Types, typename _Alloc>
2854 struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2855
2856 // See stl_pair.h...
2857 /** "piecewise construction" using a tuple of arguments for each member.
2858 *
2859 * @param __first Arguments for the first member of the pair.
2860 * @param __second Arguments for the second member of the pair.
2861 *
2862 * The elements of each tuple will be used as the constructor arguments
2863 * for the data members of the pair.
2864 */
2865 template<class _T1, class _T2>
2866 template<typename... _Args1, typename... _Args2>
2867 _GLIBCXX20_CONSTEXPR
2868 inline
2871 tuple<_Args1...> __first, tuple<_Args2...> __second)
2872 : pair(__first, __second,
2873 typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2874 typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2875 { }
2876
2877 template<class _T1, class _T2>
2878 template<typename... _Args1, size_t... _Indexes1,
2879 typename... _Args2, size_t... _Indexes2>
2880 _GLIBCXX20_CONSTEXPR inline
2882 pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2883 _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2884 : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2885 second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2886 { }
2887
2888#if defined(__cpp_lib_apply) || defined(__cpp_lib_make_from_tuple) // C++ >= 17
2889 // Unpack a std::tuple into a type trait and use its value.
2890 // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2891 // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2892 // Otherwise the result is false (because we don't know if std::get throws).
2893 template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2894 inline constexpr bool __unpack_std_tuple = false;
2895
2896 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2897 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2898 = _Trait<_Tp, _Up...>::value;
2899
2900 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2901 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2902 = _Trait<_Tp, _Up&...>::value;
2903
2904 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2905 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2906 = _Trait<_Tp, const _Up...>::value;
2907
2908 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2909 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2910 = _Trait<_Tp, const _Up&...>::value;
2911#endif
2912
2913#ifdef __cpp_lib_apply // C++ >= 17
2914 template <typename _Fn, typename _Tuple, size_t... _Idx>
2915 constexpr decltype(auto)
2916 __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2917 {
2918 return std::__invoke(std::forward<_Fn>(__f),
2919 std::get<_Idx>(std::forward<_Tuple>(__t))...);
2920 }
2921
2922#if __cpp_lib_tuple_like // >= C++23
2923 template <typename _Fn, __tuple_like _Tuple>
2924#else
2925 template <typename _Fn, typename _Tuple>
2926#endif
2927 constexpr decltype(auto)
2928 apply(_Fn&& __f, _Tuple&& __t)
2929 noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2930 {
2931 using _Indices
2932 = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2933 return std::__apply_impl(std::forward<_Fn>(__f),
2934 std::forward<_Tuple>(__t),
2935 _Indices{});
2936 }
2937#endif
2938
2939#ifdef __cpp_lib_make_from_tuple // C++ >= 17
2940 template <typename _Tp, typename _Tuple, size_t... _Idx>
2941 constexpr _Tp
2942 __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
2943 { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
2944
2945#if __cpp_lib_tuple_like // >= C++23
2946 template <typename _Tp, __tuple_like _Tuple>
2947#else
2948 template <typename _Tp, typename _Tuple>
2949#endif
2950 constexpr _Tp
2951 make_from_tuple(_Tuple&& __t)
2952 noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
2953 {
2954 constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
2955#if __has_builtin(__reference_constructs_from_temporary)
2956 if constexpr (__n == 1)
2957 {
2958 using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
2959 static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
2960 }
2961#endif
2962 return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
2963 make_index_sequence<__n>{});
2964 }
2965#endif
2966
2967#if __cpp_lib_tuple_like // >= C++23
2968 template<__tuple_like _TTuple, __tuple_like _UTuple,
2969 template<typename> class _TQual, template<typename> class _UQual,
2970 typename = make_index_sequence<tuple_size_v<_TTuple>>>
2971 struct __tuple_like_common_reference;
2972
2973 template<__tuple_like _TTuple, __tuple_like _UTuple,
2974 template<typename> class _TQual, template<typename> class _UQual,
2975 size_t... _Is>
2976 requires requires
2977 { typename tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2978 _UQual<tuple_element_t<_Is, _UTuple>>>...>; }
2979 struct __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual, index_sequence<_Is...>>
2980 {
2981 using type = tuple<common_reference_t<_TQual<tuple_element_t<_Is, _TTuple>>,
2982 _UQual<tuple_element_t<_Is, _UTuple>>>...>;
2983 };
2984
2985 template<__tuple_like _TTuple, __tuple_like _UTuple,
2986 template<typename> class _TQual, template<typename> class _UQual>
2987 requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
2988 && is_same_v<_TTuple, decay_t<_TTuple>>
2989 && is_same_v<_UTuple, decay_t<_UTuple>>
2990 && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
2991 && requires { typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type; }
2992 struct basic_common_reference<_TTuple, _UTuple, _TQual, _UQual>
2993 {
2994 using type = typename __tuple_like_common_reference<_TTuple, _UTuple, _TQual, _UQual>::type;
2995 };
2996
2997 template<__tuple_like _TTuple, __tuple_like _UTuple,
2998 typename = make_index_sequence<tuple_size_v<_TTuple>>>
2999 struct __tuple_like_common_type;
3000
3001 template<__tuple_like _TTuple, __tuple_like _UTuple, size_t... _Is>
3002 requires requires
3003 { typename tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3004 tuple_element_t<_Is, _UTuple>>...>; }
3005 struct __tuple_like_common_type<_TTuple, _UTuple, index_sequence<_Is...>>
3006 {
3007 using type = tuple<common_type_t<tuple_element_t<_Is, _TTuple>,
3008 tuple_element_t<_Is, _UTuple>>...>;
3009 };
3010
3011 template<__tuple_like _TTuple, __tuple_like _UTuple>
3012 requires (__is_tuple_v<_TTuple> || __is_tuple_v<_UTuple>)
3013 && is_same_v<_TTuple, decay_t<_TTuple>>
3014 && is_same_v<_UTuple, decay_t<_UTuple>>
3015 && (tuple_size_v<_TTuple> == tuple_size_v<_UTuple>)
3016 && requires { typename __tuple_like_common_type<_TTuple, _UTuple>::type; }
3017 struct common_type<_TTuple, _UTuple>
3018 {
3019 using type = typename __tuple_like_common_type<_TTuple, _UTuple>::type;
3020 };
3021#endif // C++23
3022
3023 /// @}
3024
3025#undef __glibcxx_no_dangling_refs
3026
3027_GLIBCXX_END_NAMESPACE_VERSION
3028} // namespace std
3029
3030#endif // C++11
3031
3032#endif // _GLIBCXX_TUPLE
constexpr bool operator<=(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:859
constexpr bool operator>=(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:873
constexpr bool operator<(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:826
constexpr bool operator>(const duration< _Rep1, _Period1 > &__lhs, const duration< _Rep2, _Period2 > &__rhs)
Definition chrono.h:866
__bool_constant< true > true_type
The type used as a compile-time boolean with true value.
Definition type_traits:116
__bool_constant< false > false_type
The type used as a compile-time boolean with false value.
Definition type_traits:119
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:2803
constexpr tuple< _Elements &&... > forward_as_tuple(_Elements &&... __args) noexcept
Create a tuple of lvalue or rvalue references to the arguments.
Definition tuple:2678
constexpr tuple< typename __decay_and_strip< _Elements >::__type... > make_tuple(_Elements &&... __args)
Create a tuple containing copies of the arguments.
Definition tuple:2666
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:2817
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:188
integer_sequence< size_t, _Idx... > index_sequence
Alias template index_sequence.
Definition utility.h:184
make_index_sequence< sizeof...(_Types)> index_sequence_for
Alias template index_sequence_for.
Definition utility.h:192
Primary class template, tuple.
Definition tuple:834
integral_constant
Definition type_traits:93
is_constructible
Definition type_traits:1158
is_nothrow_constructible
Definition type_traits:1236
is_nothrow_default_constructible
Definition type_traits:1245
is_assignable
Definition type_traits:1277
is_nothrow_assignable
Definition type_traits:1311
is_convertible
Definition type_traits:1602
Declare uses_allocator so it can be specialized in <queue> etc.
Definition memoryfwd.h:75
Struct holding two objects of arbitrary type.
Definition stl_pair.h:286
constexpr pair()
Definition stl_pair.h:727
Tag type for piecewise construction of std::pair objects.
Definition stl_pair.h:79
Finds the size of a given tuple type.
Definition utility.h:51
Gives the type of the ith element of a given tuple type.
Definition utility.h:82