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