libstdc++: tuple Source File

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