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