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