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