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