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