libstdc++
tuple
Go to the documentation of this file.
1// <tuple> -*- C++ -*-
2
3// Copyright (C) 2007-2023 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# define __cpp_lib_constexpr_tuple 201811L
46#endif
47
48namespace std _GLIBCXX_VISIBILITY(default)
49{
50_GLIBCXX_BEGIN_NAMESPACE_VERSION
51
52 /**
53 * @addtogroup utilities
54 * @{
55 */
56
57 template<typename... _Elements>
58 class tuple;
59
60 template<typename _Tp>
61 struct __is_empty_non_tuple : is_empty<_Tp> { };
62
63 // Using EBO for elements that are tuples causes ambiguous base errors.
64 template<typename _El0, typename... _El>
65 struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { };
66
67 // Use the Empty Base-class Optimization for empty, non-final types.
68 template<typename _Tp>
69 using __empty_not_final
70 = __conditional_t<__is_final(_Tp), false_type,
71 __is_empty_non_tuple<_Tp>>;
72
73 template<size_t _Idx, typename _Head,
74 bool = __empty_not_final<_Head>::value>
75 struct _Head_base;
76
77#if __has_cpp_attribute(__no_unique_address__)
78 template<size_t _Idx, typename _Head>
79 struct _Head_base<_Idx, _Head, true>
80 {
81 constexpr _Head_base()
82 : _M_head_impl() { }
83
84 constexpr _Head_base(const _Head& __h)
85 : _M_head_impl(__h) { }
86
87 constexpr _Head_base(const _Head_base&) = default;
88 constexpr _Head_base(_Head_base&&) = default;
89
90 template<typename _UHead>
91 constexpr _Head_base(_UHead&& __h)
92 : _M_head_impl(std::forward<_UHead>(__h)) { }
93
94 _GLIBCXX20_CONSTEXPR
95 _Head_base(allocator_arg_t, __uses_alloc0)
96 : _M_head_impl() { }
97
98 template<typename _Alloc>
99 _GLIBCXX20_CONSTEXPR
100 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
101 : _M_head_impl(allocator_arg, *__a._M_a) { }
102
103 template<typename _Alloc>
104 _GLIBCXX20_CONSTEXPR
105 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
106 : _M_head_impl(*__a._M_a) { }
107
108 template<typename _UHead>
109 _GLIBCXX20_CONSTEXPR
110 _Head_base(__uses_alloc0, _UHead&& __uhead)
111 : _M_head_impl(std::forward<_UHead>(__uhead)) { }
112
113 template<typename _Alloc, typename _UHead>
114 _GLIBCXX20_CONSTEXPR
115 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
116 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
117 { }
118
119 template<typename _Alloc, typename _UHead>
120 _GLIBCXX20_CONSTEXPR
121 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
122 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
123
124 static constexpr _Head&
125 _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
126
127 static constexpr const _Head&
128 _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
129
130 [[__no_unique_address__]] _Head _M_head_impl;
131 };
132#else
133 template<size_t _Idx, typename _Head>
134 struct _Head_base<_Idx, _Head, true>
135 : public _Head
136 {
137 constexpr _Head_base()
138 : _Head() { }
139
140 constexpr _Head_base(const _Head& __h)
141 : _Head(__h) { }
142
143 constexpr _Head_base(const _Head_base&) = default;
144 constexpr _Head_base(_Head_base&&) = default;
145
146 template<typename _UHead>
147 constexpr _Head_base(_UHead&& __h)
148 : _Head(std::forward<_UHead>(__h)) { }
149
150 _GLIBCXX20_CONSTEXPR
151 _Head_base(allocator_arg_t, __uses_alloc0)
152 : _Head() { }
153
154 template<typename _Alloc>
155 _GLIBCXX20_CONSTEXPR
156 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
157 : _Head(allocator_arg, *__a._M_a) { }
158
159 template<typename _Alloc>
160 _GLIBCXX20_CONSTEXPR
161 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
162 : _Head(*__a._M_a) { }
163
164 template<typename _UHead>
165 _GLIBCXX20_CONSTEXPR
166 _Head_base(__uses_alloc0, _UHead&& __uhead)
167 : _Head(std::forward<_UHead>(__uhead)) { }
168
169 template<typename _Alloc, typename _UHead>
170 _GLIBCXX20_CONSTEXPR
171 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
172 : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { }
173
174 template<typename _Alloc, typename _UHead>
175 _GLIBCXX20_CONSTEXPR
176 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
177 : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { }
178
179 static constexpr _Head&
180 _M_head(_Head_base& __b) noexcept { return __b; }
181
182 static constexpr const _Head&
183 _M_head(const _Head_base& __b) noexcept { return __b; }
184 };
185#endif
186
187 template<size_t _Idx, typename _Head>
188 struct _Head_base<_Idx, _Head, false>
189 {
190 constexpr _Head_base()
191 : _M_head_impl() { }
192
193 constexpr _Head_base(const _Head& __h)
194 : _M_head_impl(__h) { }
195
196 constexpr _Head_base(const _Head_base&) = default;
197 constexpr _Head_base(_Head_base&&) = default;
198
199 template<typename _UHead>
200 constexpr _Head_base(_UHead&& __h)
201 : _M_head_impl(std::forward<_UHead>(__h)) { }
202
203 _GLIBCXX20_CONSTEXPR
204 _Head_base(allocator_arg_t, __uses_alloc0)
205 : _M_head_impl() { }
206
207 template<typename _Alloc>
208 _GLIBCXX20_CONSTEXPR
209 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a)
210 : _M_head_impl(allocator_arg, *__a._M_a) { }
211
212 template<typename _Alloc>
213 _GLIBCXX20_CONSTEXPR
214 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a)
215 : _M_head_impl(*__a._M_a) { }
216
217 template<typename _UHead>
218 _GLIBCXX20_CONSTEXPR
219 _Head_base(__uses_alloc0, _UHead&& __uhead)
220 : _M_head_impl(std::forward<_UHead>(__uhead)) { }
221
222 template<typename _Alloc, typename _UHead>
223 _GLIBCXX20_CONSTEXPR
224 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead)
225 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead))
226 { }
227
228 template<typename _Alloc, typename _UHead>
229 _GLIBCXX20_CONSTEXPR
230 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead)
231 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { }
232
233 static constexpr _Head&
234 _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; }
235
236 static constexpr const _Head&
237 _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; }
238
239 _Head _M_head_impl;
240 };
241
242 /**
243 * Contains the actual implementation of the @c tuple template, stored
244 * as a recursive inheritance hierarchy from the first element (most
245 * derived class) to the last (least derived class). The @c Idx
246 * parameter gives the 0-based index of the element stored at this
247 * point in the hierarchy; we use it to implement a constant-time
248 * get() operation.
249 */
250 template<size_t _Idx, typename... _Elements>
251 struct _Tuple_impl;
252
253 /**
254 * Recursive tuple implementation. Here we store the @c Head element
255 * and derive from a @c Tuple_impl containing the remaining elements
256 * (which contains the @c Tail).
257 */
258 template<size_t _Idx, typename _Head, typename... _Tail>
259 struct _Tuple_impl<_Idx, _Head, _Tail...>
260 : public _Tuple_impl<_Idx + 1, _Tail...>,
261 private _Head_base<_Idx, _Head>
262 {
263 template<size_t, typename...> friend struct _Tuple_impl;
264
265 typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
266 typedef _Head_base<_Idx, _Head> _Base;
267
268 static constexpr _Head&
269 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
270
271 static constexpr const _Head&
272 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
273
274 static constexpr _Inherited&
275 _M_tail(_Tuple_impl& __t) noexcept { return __t; }
276
277 static constexpr const _Inherited&
278 _M_tail(const _Tuple_impl& __t) noexcept { return __t; }
279
280 constexpr _Tuple_impl()
281 : _Inherited(), _Base() { }
282
283 explicit constexpr
284 _Tuple_impl(const _Head& __head, const _Tail&... __tail)
285 : _Inherited(__tail...), _Base(__head)
286 { }
287
288 template<typename _UHead, typename... _UTail,
289 typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
290 explicit constexpr
291 _Tuple_impl(_UHead&& __head, _UTail&&... __tail)
292 : _Inherited(std::forward<_UTail>(__tail)...),
293 _Base(std::forward<_UHead>(__head))
294 { }
295
296 constexpr _Tuple_impl(const _Tuple_impl&) = default;
297
298 // _GLIBCXX_RESOLVE_LIB_DEFECTS
299 // 2729. Missing SFINAE on std::pair::operator=
300 _Tuple_impl& operator=(const _Tuple_impl&) = delete;
301
302 _Tuple_impl(_Tuple_impl&&) = default;
303
304 template<typename... _UElements>
305 constexpr
306 _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in)
307 : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
308 _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
309 { }
310
311 template<typename _UHead, typename... _UTails>
312 constexpr
313 _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
314 : _Inherited(std::move
315 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
316 _Base(std::forward<_UHead>
317 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
318 { }
319
320#if __cplusplus > 202002L
321 template<typename... _UElements>
322 constexpr
323 _Tuple_impl(_Tuple_impl<_Idx, _UElements...>& __in)
324 : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)),
325 _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in))
326 { }
327
328 template<typename _UHead, typename... _UTails>
329 constexpr
330 _Tuple_impl(const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
331 : _Inherited(std::move
332 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
333 _Base(std::forward<const _UHead>
334 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
335 { }
336#endif // C++23
337
338 template<typename _Alloc>
339 _GLIBCXX20_CONSTEXPR
340 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
341 : _Inherited(__tag, __a),
342 _Base(__tag, __use_alloc<_Head>(__a))
343 { }
344
345 template<typename _Alloc>
346 _GLIBCXX20_CONSTEXPR
347 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
348 const _Head& __head, const _Tail&... __tail)
349 : _Inherited(__tag, __a, __tail...),
350 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head)
351 { }
352
353 template<typename _Alloc, typename _UHead, typename... _UTail,
354 typename = __enable_if_t<sizeof...(_Tail) == sizeof...(_UTail)>>
355 _GLIBCXX20_CONSTEXPR
356 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
357 _UHead&& __head, _UTail&&... __tail)
358 : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...),
359 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
360 std::forward<_UHead>(__head))
361 { }
362
363 template<typename _Alloc>
364 _GLIBCXX20_CONSTEXPR
365 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
366 const _Tuple_impl& __in)
367 : _Inherited(__tag, __a, _M_tail(__in)),
368 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in))
369 { }
370
371 template<typename _Alloc>
372 _GLIBCXX20_CONSTEXPR
373 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
374 _Tuple_impl&& __in)
375 : _Inherited(__tag, __a, std::move(_M_tail(__in))),
376 _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
377 std::forward<_Head>(_M_head(__in)))
378 { }
379
380 template<typename _Alloc, typename _UHead, typename... _UTails>
381 _GLIBCXX20_CONSTEXPR
382 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
383 const _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
384 : _Inherited(__tag, __a,
385 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
386 _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
387 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
388 { }
389
390 template<typename _Alloc, typename _UHead, typename... _UTails>
391 _GLIBCXX20_CONSTEXPR
392 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
393 _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
394 : _Inherited(__tag, __a, std::move
395 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
396 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
397 std::forward<_UHead>
398 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
399 { }
400
401#if __cplusplus > 202002L
402 template<typename _Alloc, typename _UHead, typename... _UTails>
403 constexpr
404 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
405 _Tuple_impl<_Idx, _UHead, _UTails...>& __in)
406 : _Inherited(__tag, __a,
407 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)),
408 _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
409 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))
410 { }
411
412 template<typename _Alloc, typename _UHead, typename... _UTails>
413 constexpr
414 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a,
415 const _Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
416 : _Inherited(__tag, __a, std::move
417 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))),
418 _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
419 std::forward<const _UHead>
420 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)))
421 { }
422#endif // C++23
423
424 template<typename... _UElements>
425 _GLIBCXX20_CONSTEXPR
426 void
427 _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in)
428 {
429 _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
430 _M_tail(*this)._M_assign(
431 _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
432 }
433
434 template<typename _UHead, typename... _UTails>
435 _GLIBCXX20_CONSTEXPR
436 void
437 _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
438 {
439 _M_head(*this) = std::forward<_UHead>
440 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
441 _M_tail(*this)._M_assign(
442 std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
443 }
444
445#if __cplusplus > 202002L
446 template<typename... _UElements>
447 constexpr void
448 _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) const
449 {
450 _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
451 _M_tail(*this)._M_assign(
452 _Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
453 }
454
455 template<typename _UHead, typename... _UTails>
456 constexpr void
457 _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) const
458 {
459 _M_head(*this) = std::forward<_UHead>
460 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
461 _M_tail(*this)._M_assign(
462 std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
463 }
464#endif // C++23
465
466 protected:
467 _GLIBCXX20_CONSTEXPR
468 void
469 _M_swap(_Tuple_impl& __in)
470 {
471 using std::swap;
472 swap(_M_head(*this), _M_head(__in));
473 _Inherited::_M_swap(_M_tail(__in));
474 }
475
476#if __cplusplus > 202002L
477 constexpr void
478 _M_swap(const _Tuple_impl& __in) const
479 {
480 using std::swap;
481 swap(_M_head(*this), _M_head(__in));
482 _Inherited::_M_swap(_M_tail(__in));
483 }
484#endif // C++23
485 };
486
487 // Basis case of inheritance recursion.
488 template<size_t _Idx, typename _Head>
489 struct _Tuple_impl<_Idx, _Head>
490 : private _Head_base<_Idx, _Head>
491 {
492 template<size_t, typename...> friend struct _Tuple_impl;
493
494 typedef _Head_base<_Idx, _Head> _Base;
495
496 static constexpr _Head&
497 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
498
499 static constexpr const _Head&
500 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); }
501
502 constexpr
503 _Tuple_impl()
504 : _Base() { }
505
506 explicit constexpr
507 _Tuple_impl(const _Head& __head)
508 : _Base(__head)
509 { }
510
511 template<typename _UHead>
512 explicit constexpr
513 _Tuple_impl(_UHead&& __head)
514 : _Base(std::forward<_UHead>(__head))
515 { }
516
517 constexpr _Tuple_impl(const _Tuple_impl&) = default;
518
519 // _GLIBCXX_RESOLVE_LIB_DEFECTS
520 // 2729. Missing SFINAE on std::pair::operator=
521 _Tuple_impl& operator=(const _Tuple_impl&) = delete;
522
523#if _GLIBCXX_INLINE_VERSION
524 _Tuple_impl(_Tuple_impl&&) = default;
525#else
526 constexpr
527 _Tuple_impl(_Tuple_impl&& __in)
528 noexcept(is_nothrow_move_constructible<_Head>::value)
529 : _Base(static_cast<_Base&&>(__in))
530 { }
531#endif
532
533 template<typename _UHead>
534 constexpr
535 _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in)
536 : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
537 { }
538
539 template<typename _UHead>
540 constexpr
541 _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in)
542 : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
543 { }
544
545#if __cplusplus > 202002L
546 template<typename _UHead>
547 constexpr
548 _Tuple_impl(_Tuple_impl<_Idx, _UHead>& __in)
549 : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in))
550 { }
551
552 template<typename _UHead>
553 constexpr
554 _Tuple_impl(const _Tuple_impl<_Idx, _UHead>&& __in)
555 : _Base(std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
556 { }
557#endif // C++23
558
559 template<typename _Alloc>
560 _GLIBCXX20_CONSTEXPR
561 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a)
562 : _Base(__tag, __use_alloc<_Head>(__a))
563 { }
564
565 template<typename _Alloc>
566 _GLIBCXX20_CONSTEXPR
567 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
568 const _Head& __head)
569 : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), __head)
570 { }
571
572 template<typename _Alloc, typename _UHead>
573 _GLIBCXX20_CONSTEXPR
574 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
575 _UHead&& __head)
576 : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
577 std::forward<_UHead>(__head))
578 { }
579
580 template<typename _Alloc>
581 _GLIBCXX20_CONSTEXPR
582 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
583 const _Tuple_impl& __in)
584 : _Base(__use_alloc<_Head, _Alloc, const _Head&>(__a), _M_head(__in))
585 { }
586
587 template<typename _Alloc>
588 _GLIBCXX20_CONSTEXPR
589 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
590 _Tuple_impl&& __in)
591 : _Base(__use_alloc<_Head, _Alloc, _Head>(__a),
592 std::forward<_Head>(_M_head(__in)))
593 { }
594
595 template<typename _Alloc, typename _UHead>
596 _GLIBCXX20_CONSTEXPR
597 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
598 const _Tuple_impl<_Idx, _UHead>& __in)
599 : _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a),
600 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
601 { }
602
603 template<typename _Alloc, typename _UHead>
604 _GLIBCXX20_CONSTEXPR
605 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
606 _Tuple_impl<_Idx, _UHead>&& __in)
607 : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a),
608 std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
609 { }
610
611#if __cplusplus > 202002L
612 template<typename _Alloc, typename _UHead>
613 constexpr
614 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
615 _Tuple_impl<_Idx, _UHead>& __in)
616 : _Base(__use_alloc<_Head, _Alloc, _UHead&>(__a),
617 _Tuple_impl<_Idx, _UHead>::_M_head(__in))
618 { }
619
620 template<typename _Alloc, typename _UHead>
621 constexpr
622 _Tuple_impl(allocator_arg_t, const _Alloc& __a,
623 const _Tuple_impl<_Idx, _UHead>&& __in)
624 : _Base(__use_alloc<_Head, _Alloc, const _UHead>(__a),
625 std::forward<const _UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
626 { }
627#endif // C++23
628
629 template<typename _UHead>
630 _GLIBCXX20_CONSTEXPR
631 void
632 _M_assign(const _Tuple_impl<_Idx, _UHead>& __in)
633 {
634 _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
635 }
636
637 template<typename _UHead>
638 _GLIBCXX20_CONSTEXPR
639 void
640 _M_assign(_Tuple_impl<_Idx, _UHead>&& __in)
641 {
642 _M_head(*this)
643 = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
644 }
645
646#if __cplusplus > 202002L
647 template<typename _UHead>
648 constexpr void
649 _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) const
650 {
651 _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
652 }
653
654 template<typename _UHead>
655 constexpr void
656 _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) const
657 {
658 _M_head(*this)
659 = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
660 }
661#endif // C++23
662
663 protected:
664 _GLIBCXX20_CONSTEXPR
665 void
666 _M_swap(_Tuple_impl& __in)
667 {
668 using std::swap;
669 swap(_M_head(*this), _M_head(__in));
670 }
671
672#if __cplusplus > 202002L
673 constexpr void
674 _M_swap(const _Tuple_impl& __in) const
675 {
676 using std::swap;
677 swap(_M_head(*this), _M_head(__in));
678 }
679#endif // C++23
680 };
681
682 // Concept utility functions, reused in conditionally-explicit
683 // constructors.
684 template<bool, typename... _Types>
685 struct _TupleConstraints
686 {
687 template<typename... _UTypes>
688 using __constructible = __and_<is_constructible<_Types, _UTypes>...>;
689
690 template<typename... _UTypes>
691 using __convertible = __and_<is_convertible<_UTypes, _Types>...>;
692
693 // Constraint for a non-explicit constructor.
694 // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
695 // and every Ui is implicitly convertible to Ti.
696 template<typename... _UTypes>
697 static constexpr bool __is_implicitly_constructible()
698 {
699 return __and_<__constructible<_UTypes...>,
700 __convertible<_UTypes...>
701 >::value;
702 }
703
704 // Constraint for a non-explicit constructor.
705 // True iff each Ti in _Types... can be constructed from Ui in _UTypes...
706 // but not every Ui is implicitly convertible to Ti.
707 template<typename... _UTypes>
708 static constexpr bool __is_explicitly_constructible()
709 {
710 return __and_<__constructible<_UTypes...>,
711 __not_<__convertible<_UTypes...>>
712 >::value;
713 }
714
715 static constexpr bool __is_implicitly_default_constructible()
716 {
717 return __and_<std::__is_implicitly_default_constructible<_Types>...
718 >::value;
719 }
720
721 static constexpr bool __is_explicitly_default_constructible()
722 {
723 return __and_<is_default_constructible<_Types>...,
724 __not_<__and_<
725 std::__is_implicitly_default_constructible<_Types>...>
726 >>::value;
727 }
728 };
729
730 // Partial specialization used when a required precondition isn't met,
731 // e.g. when sizeof...(_Types) != sizeof...(_UTypes).
732 template<typename... _Types>
733 struct _TupleConstraints<false, _Types...>
734 {
735 template<typename... _UTypes>
736 static constexpr bool __is_implicitly_constructible()
737 { return false; }
738
739 template<typename... _UTypes>
740 static constexpr bool __is_explicitly_constructible()
741 { return false; }
742 };
743
744 /// Primary class template, tuple
745 template<typename... _Elements>
746 class tuple : public _Tuple_impl<0, _Elements...>
747 {
748 typedef _Tuple_impl<0, _Elements...> _Inherited;
749
750 template<bool _Cond>
751 using _TCC = _TupleConstraints<_Cond, _Elements...>;
752
753 // Constraint for non-explicit default constructor
754 template<bool _Dummy>
755 using _ImplicitDefaultCtor = __enable_if_t<
756 _TCC<_Dummy>::__is_implicitly_default_constructible(),
757 bool>;
758
759 // Constraint for explicit default constructor
760 template<bool _Dummy>
761 using _ExplicitDefaultCtor = __enable_if_t<
762 _TCC<_Dummy>::__is_explicitly_default_constructible(),
763 bool>;
764
765 // Constraint for non-explicit constructors
766 template<bool _Cond, typename... _Args>
767 using _ImplicitCtor = __enable_if_t<
768 _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(),
769 bool>;
770
771 // Constraint for non-explicit constructors
772 template<bool _Cond, typename... _Args>
773 using _ExplicitCtor = __enable_if_t<
774 _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(),
775 bool>;
776
777 template<typename... _UElements>
778 static constexpr
779 __enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool>
780 __assignable()
781 { return __and_<is_assignable<_Elements&, _UElements>...>::value; }
782
783 // Condition for noexcept-specifier of an assignment operator.
784 template<typename... _UElements>
785 static constexpr bool __nothrow_assignable()
786 {
787 return
788 __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value;
789 }
790
791 // Condition for noexcept-specifier of a constructor.
792 template<typename... _UElements>
793 static constexpr bool __nothrow_constructible()
794 {
795 return
796 __and_<is_nothrow_constructible<_Elements, _UElements>...>::value;
797 }
798
799 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1.
800 template<typename _Up>
801 static constexpr bool __valid_args()
802 {
803 return sizeof...(_Elements) == 1
804 && !is_same<tuple, __remove_cvref_t<_Up>>::value;
805 }
806
807 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1.
808 template<typename, typename, typename... _Tail>
809 static constexpr bool __valid_args()
810 { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); }
811
812 /* Constraint for constructors with a tuple<UTypes...> parameter ensures
813 * that the constructor is only viable when it would not interfere with
814 * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&).
815 * Such constructors are only viable if:
816 * either sizeof...(Types) != 1,
817 * or (when Types... expands to T and UTypes... expands to U)
818 * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>,
819 * and is_same_v<T, U> are all false.
820 */
821 template<typename _Tuple, typename = tuple,
822 typename = __remove_cvref_t<_Tuple>>
823 struct _UseOtherCtor
824 : false_type
825 { };
826 // If TUPLE is convertible to the single element in *this,
827 // then TUPLE should match tuple(UTypes&&...) instead.
828 template<typename _Tuple, typename _Tp, typename _Up>
829 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>>
830 : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>>::type
831 { };
832 // If TUPLE and *this each have a single element of the same type,
833 // then TUPLE should match a copy/move constructor instead.
834 template<typename _Tuple, typename _Tp>
835 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>>
836 : true_type
837 { };
838
839 // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1
840 // and the single element in Types can be initialized from TUPLE,
841 // or is the same type as tuple_element_t<0, TUPLE>.
842 template<typename _Tuple>
843 static constexpr bool __use_other_ctor()
844 { return _UseOtherCtor<_Tuple>::value; }
845
846#if __cplusplus > 202002L
847 template<typename... _Args>
848 static constexpr bool __constructible
849 = _TCC<true>::template __constructible<_Args...>::value;
850
851 template<typename... _Args>
852 static constexpr bool __convertible
853 = _TCC<true>::template __convertible<_Args...>::value;
854#endif // C++23
855
856 public:
857 template<typename _Dummy = void,
858 _ImplicitDefaultCtor<is_void<_Dummy>::value> = true>
859 constexpr
860 tuple()
861 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
862 : _Inherited() { }
863
864 template<typename _Dummy = void,
865 _ExplicitDefaultCtor<is_void<_Dummy>::value> = false>
866 explicit constexpr
867 tuple()
868 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value)
869 : _Inherited() { }
870
871 template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
872 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
873 constexpr
874 tuple(const _Elements&... __elements)
875 noexcept(__nothrow_constructible<const _Elements&...>())
876 : _Inherited(__elements...) { }
877
878 template<bool _NotEmpty = (sizeof...(_Elements) >= 1),
879 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
880 explicit constexpr
881 tuple(const _Elements&... __elements)
882 noexcept(__nothrow_constructible<const _Elements&...>())
883 : _Inherited(__elements...) { }
884
885 template<typename... _UElements,
886 bool _Valid = __valid_args<_UElements...>(),
887 _ImplicitCtor<_Valid, _UElements...> = true>
888 constexpr
889 tuple(_UElements&&... __elements)
890 noexcept(__nothrow_constructible<_UElements...>())
891 : _Inherited(std::forward<_UElements>(__elements)...) { }
892
893 template<typename... _UElements,
894 bool _Valid = __valid_args<_UElements...>(),
895 _ExplicitCtor<_Valid, _UElements...> = false>
896 explicit constexpr
897 tuple(_UElements&&... __elements)
898 noexcept(__nothrow_constructible<_UElements...>())
899 : _Inherited(std::forward<_UElements>(__elements)...) { }
900
901 constexpr tuple(const tuple&) = default;
902
903 constexpr tuple(tuple&&) = default;
904
905 template<typename... _UElements,
906 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
907 && !__use_other_ctor<const tuple<_UElements...>&>(),
908 _ImplicitCtor<_Valid, const _UElements&...> = true>
909 constexpr
910 tuple(const tuple<_UElements...>& __in)
911 noexcept(__nothrow_constructible<const _UElements&...>())
912 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
913 { }
914
915 template<typename... _UElements,
916 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
917 && !__use_other_ctor<const tuple<_UElements...>&>(),
918 _ExplicitCtor<_Valid, const _UElements&...> = false>
919 explicit constexpr
920 tuple(const tuple<_UElements...>& __in)
921 noexcept(__nothrow_constructible<const _UElements&...>())
922 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
923 { }
924
925 template<typename... _UElements,
926 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
927 && !__use_other_ctor<tuple<_UElements...>&&>(),
928 _ImplicitCtor<_Valid, _UElements...> = true>
929 constexpr
930 tuple(tuple<_UElements...>&& __in)
931 noexcept(__nothrow_constructible<_UElements...>())
932 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
933
934 template<typename... _UElements,
935 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
936 && !__use_other_ctor<tuple<_UElements...>&&>(),
937 _ExplicitCtor<_Valid, _UElements...> = false>
938 explicit constexpr
939 tuple(tuple<_UElements...>&& __in)
940 noexcept(__nothrow_constructible<_UElements...>())
941 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
942
943#if __cplusplus > 202002L
944 template<typename... _UElements>
945 requires (sizeof...(_Elements) == sizeof...(_UElements))
946 && (!__use_other_ctor<tuple<_UElements...>&>())
947 && __constructible<_UElements&...>
948 explicit(!__convertible<_UElements&...>)
949 constexpr
950 tuple(tuple<_UElements...>& __in)
951 noexcept(__nothrow_constructible<_UElements&...>())
952 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&>(__in))
953 { }
954
955 template<typename... _UElements>
956 requires (sizeof...(_Elements) == sizeof...(_UElements))
957 && (!__use_other_ctor<const tuple<_UElements...>&&>())
958 && __constructible<const _UElements...>
959 explicit(!__convertible<const _UElements...>)
960 constexpr
961 tuple(const tuple<_UElements...>&& __in)
962 noexcept(__nothrow_constructible<const _UElements...>())
963 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&&>(__in)) { }
964#endif // C++23
965
966 // Allocator-extended constructors.
967
968 template<typename _Alloc,
969 _ImplicitDefaultCtor<is_object<_Alloc>::value> = true>
970 _GLIBCXX20_CONSTEXPR
971 tuple(allocator_arg_t __tag, const _Alloc& __a)
972 : _Inherited(__tag, __a) { }
973
974 template<typename _Alloc,
975 _ExplicitDefaultCtor<is_object<_Alloc>::value> = false>
976 _GLIBCXX20_CONSTEXPR
977 explicit
978 tuple(allocator_arg_t __tag, const _Alloc& __a)
979 : _Inherited(__tag, __a) { }
980
981 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
982 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
983 _GLIBCXX20_CONSTEXPR
984 tuple(allocator_arg_t __tag, const _Alloc& __a,
985 const _Elements&... __elements)
986 : _Inherited(__tag, __a, __elements...) { }
987
988 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
989 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
990 _GLIBCXX20_CONSTEXPR
991 explicit
992 tuple(allocator_arg_t __tag, const _Alloc& __a,
993 const _Elements&... __elements)
994 : _Inherited(__tag, __a, __elements...) { }
995
996 template<typename _Alloc, typename... _UElements,
997 bool _Valid = __valid_args<_UElements...>(),
998 _ImplicitCtor<_Valid, _UElements...> = true>
999 _GLIBCXX20_CONSTEXPR
1000 tuple(allocator_arg_t __tag, const _Alloc& __a,
1001 _UElements&&... __elements)
1002 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1003 { }
1004
1005 template<typename _Alloc, typename... _UElements,
1006 bool _Valid = __valid_args<_UElements...>(),
1007 _ExplicitCtor<_Valid, _UElements...> = false>
1008 _GLIBCXX20_CONSTEXPR
1009 explicit
1010 tuple(allocator_arg_t __tag, const _Alloc& __a,
1011 _UElements&&... __elements)
1012 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1013 { }
1014
1015 template<typename _Alloc>
1016 _GLIBCXX20_CONSTEXPR
1017 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1018 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1019
1020 template<typename _Alloc>
1021 _GLIBCXX20_CONSTEXPR
1022 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1023 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1024
1025 template<typename _Alloc, typename... _UElements,
1026 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1027 && !__use_other_ctor<const tuple<_UElements...>&>(),
1028 _ImplicitCtor<_Valid, const _UElements&...> = true>
1029 _GLIBCXX20_CONSTEXPR
1030 tuple(allocator_arg_t __tag, const _Alloc& __a,
1031 const tuple<_UElements...>& __in)
1032 : _Inherited(__tag, __a,
1033 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1034 { }
1035
1036 template<typename _Alloc, typename... _UElements,
1037 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1038 && !__use_other_ctor<const tuple<_UElements...>&>(),
1039 _ExplicitCtor<_Valid, const _UElements&...> = false>
1040 _GLIBCXX20_CONSTEXPR
1041 explicit
1042 tuple(allocator_arg_t __tag, const _Alloc& __a,
1043 const tuple<_UElements...>& __in)
1044 : _Inherited(__tag, __a,
1045 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1046 { }
1047
1048 template<typename _Alloc, typename... _UElements,
1049 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1050 && !__use_other_ctor<tuple<_UElements...>&&>(),
1051 _ImplicitCtor<_Valid, _UElements...> = true>
1052 _GLIBCXX20_CONSTEXPR
1053 tuple(allocator_arg_t __tag, const _Alloc& __a,
1054 tuple<_UElements...>&& __in)
1055 : _Inherited(__tag, __a,
1056 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1057 { }
1058
1059 template<typename _Alloc, typename... _UElements,
1060 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1061 && !__use_other_ctor<tuple<_UElements...>&&>(),
1062 _ExplicitCtor<_Valid, _UElements...> = false>
1063 _GLIBCXX20_CONSTEXPR
1064 explicit
1065 tuple(allocator_arg_t __tag, const _Alloc& __a,
1066 tuple<_UElements...>&& __in)
1067 : _Inherited(__tag, __a,
1068 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1069 { }
1070
1071#if __cplusplus > 202002L
1072 template<typename _Alloc, typename... _UElements>
1073 requires (sizeof...(_Elements) == sizeof...(_UElements))
1074 && (!__use_other_ctor<tuple<_UElements...>&>())
1075 && __constructible<_UElements&...>
1076 explicit(!__convertible<_UElements&...>)
1077 constexpr
1078 tuple(allocator_arg_t __tag, const _Alloc& __a,
1079 tuple<_UElements...>& __in)
1080 : _Inherited(__tag, __a,
1081 static_cast<_Tuple_impl<0, _UElements...>&>(__in))
1082 { }
1083
1084 template<typename _Alloc, typename... _UElements>
1085 requires (sizeof...(_Elements) == sizeof...(_UElements))
1086 && (!__use_other_ctor<const tuple<_UElements...>>())
1087 && __constructible<const _UElements...>
1088 explicit(!__convertible<const _UElements...>)
1089 constexpr
1090 tuple(allocator_arg_t __tag, const _Alloc& __a,
1091 const tuple<_UElements...>&& __in)
1092 : _Inherited(__tag, __a,
1093 static_cast<const _Tuple_impl<0, _UElements...>&&>(__in))
1094 { }
1095#endif // C++23
1096
1097 // tuple assignment
1098
1099 _GLIBCXX20_CONSTEXPR
1100 tuple&
1101 operator=(__conditional_t<__assignable<const _Elements&...>(),
1102 const tuple&,
1103 const __nonesuch&> __in)
1104 noexcept(__nothrow_assignable<const _Elements&...>())
1105 {
1106 this->_M_assign(__in);
1107 return *this;
1108 }
1109
1110 _GLIBCXX20_CONSTEXPR
1111 tuple&
1112 operator=(__conditional_t<__assignable<_Elements...>(),
1113 tuple&&,
1114 __nonesuch&&> __in)
1115 noexcept(__nothrow_assignable<_Elements...>())
1116 {
1117 this->_M_assign(std::move(__in));
1118 return *this;
1119 }
1120
1121 template<typename... _UElements>
1122 _GLIBCXX20_CONSTEXPR
1123 __enable_if_t<__assignable<const _UElements&...>(), tuple&>
1124 operator=(const tuple<_UElements...>& __in)
1125 noexcept(__nothrow_assignable<const _UElements&...>())
1126 {
1127 this->_M_assign(__in);
1128 return *this;
1129 }
1130
1131 template<typename... _UElements>
1132 _GLIBCXX20_CONSTEXPR
1133 __enable_if_t<__assignable<_UElements...>(), tuple&>
1134 operator=(tuple<_UElements...>&& __in)
1135 noexcept(__nothrow_assignable<_UElements...>())
1136 {
1137 this->_M_assign(std::move(__in));
1138 return *this;
1139 }
1140
1141#if __cplusplus > 202002L
1142 constexpr const tuple&
1143 operator=(const tuple& __in) const
1144 requires (is_copy_assignable_v<const _Elements> && ...)
1145 {
1146 this->_M_assign(__in);
1147 return *this;
1148 }
1149
1150 constexpr const tuple&
1151 operator=(tuple&& __in) const
1152 requires (is_assignable_v<const _Elements&, _Elements> && ...)
1153 {
1154 this->_M_assign(std::move(__in));
1155 return *this;
1156 }
1157
1158 template<typename... _UElements>
1159 constexpr const tuple&
1160 operator=(const tuple<_UElements...>& __in) const
1161 requires (sizeof...(_Elements) == sizeof...(_UElements))
1162 && (is_assignable_v<const _Elements&, const _UElements&> && ...)
1163 {
1164 this->_M_assign(__in);
1165 return *this;
1166 }
1167
1168 template<typename... _UElements>
1169 constexpr const tuple&
1170 operator=(tuple<_UElements...>&& __in) const
1171 requires (sizeof...(_Elements) == sizeof...(_UElements))
1172 && (is_assignable_v<const _Elements&, _UElements> && ...)
1173 {
1174 this->_M_assign(std::move(__in));
1175 return *this;
1176 }
1177#endif // C++23
1178
1179 // tuple swap
1180 _GLIBCXX20_CONSTEXPR
1181 void
1182 swap(tuple& __in)
1183 noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
1184 { _Inherited::_M_swap(__in); }
1185
1186#if __cplusplus > 202002L
1187 // As an extension, we constrain the const swap member function in order
1188 // to continue accepting explicit instantiation of tuples whose elements
1189 // are not all const swappable. Without this constraint, such an
1190 // explicit instantiation would also instantiate the ill-formed body of
1191 // this function and yield a hard error. This constraint shouldn't
1192 // affect the behavior of valid programs.
1193 constexpr void
1194 swap(const tuple& __in) const
1195 noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
1196 requires (is_swappable_v<const _Elements> && ...)
1197 { _Inherited::_M_swap(__in); }
1198#endif // C++23
1199 };
1200
1201#if __cpp_deduction_guides >= 201606
1202 template<typename... _UTypes>
1203 tuple(_UTypes...) -> tuple<_UTypes...>;
1204 template<typename _T1, typename _T2>
1205 tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
1206 template<typename _Alloc, typename... _UTypes>
1207 tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
1208 template<typename _Alloc, typename _T1, typename _T2>
1209 tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
1210 template<typename _Alloc, typename... _UTypes>
1211 tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
1212#endif
1213
1214 // Explicit specialization, zero-element tuple.
1215 template<>
1216 class tuple<>
1217 {
1218 public:
1219 _GLIBCXX20_CONSTEXPR
1220 void swap(tuple&) noexcept { /* no-op */ }
1221#if __cplusplus > 202002L
1222 constexpr void swap(const tuple&) const noexcept { /* no-op */ }
1223#endif
1224 // We need the default since we're going to define no-op
1225 // allocator constructors.
1226 tuple() = default;
1227 // No-op allocator constructors.
1228 template<typename _Alloc>
1229 _GLIBCXX20_CONSTEXPR
1230 tuple(allocator_arg_t, const _Alloc&) noexcept { }
1231 template<typename _Alloc>
1232 _GLIBCXX20_CONSTEXPR
1233 tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
1234 };
1235
1236 /// Partial specialization, 2-element tuple.
1237 /// Includes construction and assignment from a pair.
1238 template<typename _T1, typename _T2>
1239 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
1240 {
1241 typedef _Tuple_impl<0, _T1, _T2> _Inherited;
1242
1243 // Constraint for non-explicit default constructor
1244 template<bool _Dummy, typename _U1, typename _U2>
1245 using _ImplicitDefaultCtor = __enable_if_t<
1246 _TupleConstraints<_Dummy, _U1, _U2>::
1247 __is_implicitly_default_constructible(),
1248 bool>;
1249
1250 // Constraint for explicit default constructor
1251 template<bool _Dummy, typename _U1, typename _U2>
1252 using _ExplicitDefaultCtor = __enable_if_t<
1253 _TupleConstraints<_Dummy, _U1, _U2>::
1254 __is_explicitly_default_constructible(),
1255 bool>;
1256
1257 template<bool _Dummy>
1258 using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
1259
1260 // Constraint for non-explicit constructors
1261 template<bool _Cond, typename _U1, typename _U2>
1262 using _ImplicitCtor = __enable_if_t<
1263 _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
1264 bool>;
1265
1266 // Constraint for non-explicit constructors
1267 template<bool _Cond, typename _U1, typename _U2>
1268 using _ExplicitCtor = __enable_if_t<
1269 _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
1270 bool>;
1271
1272 template<typename _U1, typename _U2>
1273 static constexpr bool __assignable()
1274 {
1275 return __and_<is_assignable<_T1&, _U1>,
1276 is_assignable<_T2&, _U2>>::value;
1277 }
1278
1279 template<typename _U1, typename _U2>
1280 static constexpr bool __nothrow_assignable()
1281 {
1282 return __and_<is_nothrow_assignable<_T1&, _U1>,
1283 is_nothrow_assignable<_T2&, _U2>>::value;
1284 }
1285
1286 template<typename _U1, typename _U2>
1287 static constexpr bool __nothrow_constructible()
1288 {
1289 return __and_<is_nothrow_constructible<_T1, _U1>,
1290 is_nothrow_constructible<_T2, _U2>>::value;
1291 }
1292
1293 static constexpr bool __nothrow_default_constructible()
1294 {
1295 return __and_<is_nothrow_default_constructible<_T1>,
1296 is_nothrow_default_constructible<_T2>>::value;
1297 }
1298
1299 template<typename _U1>
1300 static constexpr bool __is_alloc_arg()
1301 { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
1302
1303#if __cplusplus > 202002L
1304 template<typename _U1, typename _U2>
1305 static constexpr bool __constructible
1306 = _TCC<true>::template __constructible<_U1, _U2>::value;
1307
1308 template<typename _U1, typename _U2>
1309 static constexpr bool __convertible
1310 = _TCC<true>::template __convertible<_U1, _U2>::value;
1311#endif // C++23
1312
1313 public:
1314 template<bool _Dummy = true,
1315 _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
1316 constexpr
1317 tuple()
1318 noexcept(__nothrow_default_constructible())
1319 : _Inherited() { }
1320
1321 template<bool _Dummy = true,
1322 _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
1323 explicit constexpr
1324 tuple()
1325 noexcept(__nothrow_default_constructible())
1326 : _Inherited() { }
1327
1328 template<bool _Dummy = true,
1329 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
1330 constexpr
1331 tuple(const _T1& __a1, const _T2& __a2)
1332 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
1333 : _Inherited(__a1, __a2) { }
1334
1335 template<bool _Dummy = true,
1336 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
1337 explicit constexpr
1338 tuple(const _T1& __a1, const _T2& __a2)
1339 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
1340 : _Inherited(__a1, __a2) { }
1341
1342 template<typename _U1, typename _U2,
1343 _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
1344 constexpr
1345 tuple(_U1&& __a1, _U2&& __a2)
1346 noexcept(__nothrow_constructible<_U1, _U2>())
1347 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
1348
1349 template<typename _U1, typename _U2,
1350 _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
1351 explicit constexpr
1352 tuple(_U1&& __a1, _U2&& __a2)
1353 noexcept(__nothrow_constructible<_U1, _U2>())
1354 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
1355
1356 constexpr tuple(const tuple&) = default;
1357
1358 constexpr tuple(tuple&&) = default;
1359
1360 template<typename _U1, typename _U2,
1361 _ImplicitCtor<true, const _U1&, const _U2&> = true>
1362 constexpr
1363 tuple(const tuple<_U1, _U2>& __in)
1364 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1365 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
1366
1367 template<typename _U1, typename _U2,
1368 _ExplicitCtor<true, const _U1&, const _U2&> = false>
1369 explicit constexpr
1370 tuple(const tuple<_U1, _U2>& __in)
1371 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1372 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
1373
1374 template<typename _U1, typename _U2,
1375 _ImplicitCtor<true, _U1, _U2> = true>
1376 constexpr
1377 tuple(tuple<_U1, _U2>&& __in)
1378 noexcept(__nothrow_constructible<_U1, _U2>())
1379 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
1380
1381 template<typename _U1, typename _U2,
1382 _ExplicitCtor<true, _U1, _U2> = false>
1383 explicit constexpr
1384 tuple(tuple<_U1, _U2>&& __in)
1385 noexcept(__nothrow_constructible<_U1, _U2>())
1386 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
1387
1388#if __cplusplus > 202002L
1389 template<typename _U1, typename _U2>
1390 requires __constructible<_U1&, _U2&>
1391 explicit(!__convertible<_U1&, _U2&>)
1392 constexpr
1393 tuple(tuple<_U1, _U2>& __in)
1394 noexcept(__nothrow_constructible<_U1&, _U2&>())
1395 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&>(__in)) { }
1396
1397 template<typename _U1, typename _U2>
1398 requires __constructible<const _U1, const _U2>
1399 explicit(!__convertible<const _U1, const _U2>)
1400 constexpr
1401 tuple(const tuple<_U1, _U2>&& __in)
1402 noexcept(__nothrow_constructible<const _U1, const _U2>())
1403 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&&>(__in)) { }
1404#endif // C++23
1405
1406 template<typename _U1, typename _U2,
1407 _ImplicitCtor<true, const _U1&, const _U2&> = true>
1408 constexpr
1409 tuple(const pair<_U1, _U2>& __in)
1410 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1411 : _Inherited(__in.first, __in.second) { }
1412
1413 template<typename _U1, typename _U2,
1414 _ExplicitCtor<true, const _U1&, const _U2&> = false>
1415 explicit constexpr
1416 tuple(const pair<_U1, _U2>& __in)
1417 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1418 : _Inherited(__in.first, __in.second) { }
1419
1420 template<typename _U1, typename _U2,
1421 _ImplicitCtor<true, _U1, _U2> = true>
1422 constexpr
1423 tuple(pair<_U1, _U2>&& __in)
1424 noexcept(__nothrow_constructible<_U1, _U2>())
1425 : _Inherited(std::forward<_U1>(__in.first),
1426 std::forward<_U2>(__in.second)) { }
1427
1428 template<typename _U1, typename _U2,
1429 _ExplicitCtor<true, _U1, _U2> = false>
1430 explicit constexpr
1431 tuple(pair<_U1, _U2>&& __in)
1432 noexcept(__nothrow_constructible<_U1, _U2>())
1433 : _Inherited(std::forward<_U1>(__in.first),
1434 std::forward<_U2>(__in.second)) { }
1435
1436#if __cplusplus > 202002L
1437 template<typename _U1, typename _U2>
1438 requires __constructible<_U1&, _U2&>
1439 explicit(!__convertible<_U1&, _U2&>)
1440 constexpr
1441 tuple(pair<_U1, _U2>& __in)
1442 noexcept(__nothrow_constructible<_U1&, _U2&>())
1443 : _Inherited(__in.first, __in.second) { }
1444
1445 template<typename _U1, typename _U2>
1446 requires __constructible<const _U1, const _U2>
1447 explicit(!__convertible<const _U1, const _U2>)
1448 constexpr
1449 tuple(const pair<_U1, _U2>&& __in)
1450 noexcept(__nothrow_constructible<const _U1, const _U2>())
1451 : _Inherited(std::forward<const _U1>(__in.first),
1452 std::forward<const _U2>(__in.second)) { }
1453#endif // C++23
1454
1455 // Allocator-extended constructors.
1456
1457 template<typename _Alloc,
1458 _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
1459 _GLIBCXX20_CONSTEXPR
1460 tuple(allocator_arg_t __tag, const _Alloc& __a)
1461 : _Inherited(__tag, __a) { }
1462
1463 template<typename _Alloc,
1464 _ExplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = false>
1465 _GLIBCXX20_CONSTEXPR
1466 explicit
1467 tuple(allocator_arg_t __tag, const _Alloc& __a)
1468 : _Inherited(__tag, __a) { }
1469
1470 template<typename _Alloc, bool _Dummy = true,
1471 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
1472 _GLIBCXX20_CONSTEXPR
1473 tuple(allocator_arg_t __tag, const _Alloc& __a,
1474 const _T1& __a1, const _T2& __a2)
1475 : _Inherited(__tag, __a, __a1, __a2) { }
1476
1477 template<typename _Alloc, bool _Dummy = true,
1478 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
1479 explicit
1480 _GLIBCXX20_CONSTEXPR
1481 tuple(allocator_arg_t __tag, const _Alloc& __a,
1482 const _T1& __a1, const _T2& __a2)
1483 : _Inherited(__tag, __a, __a1, __a2) { }
1484
1485 template<typename _Alloc, typename _U1, typename _U2,
1486 _ImplicitCtor<true, _U1, _U2> = true>
1487 _GLIBCXX20_CONSTEXPR
1488 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
1489 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
1490 std::forward<_U2>(__a2)) { }
1491
1492 template<typename _Alloc, typename _U1, typename _U2,
1493 _ExplicitCtor<true, _U1, _U2> = false>
1494 explicit
1495 _GLIBCXX20_CONSTEXPR
1496 tuple(allocator_arg_t __tag, const _Alloc& __a,
1497 _U1&& __a1, _U2&& __a2)
1498 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
1499 std::forward<_U2>(__a2)) { }
1500
1501 template<typename _Alloc>
1502 _GLIBCXX20_CONSTEXPR
1503 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1504 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1505
1506 template<typename _Alloc>
1507 _GLIBCXX20_CONSTEXPR
1508 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1509 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1510
1511 template<typename _Alloc, typename _U1, typename _U2,
1512 _ImplicitCtor<true, const _U1&, const _U2&> = true>
1513 _GLIBCXX20_CONSTEXPR
1514 tuple(allocator_arg_t __tag, const _Alloc& __a,
1515 const tuple<_U1, _U2>& __in)
1516 : _Inherited(__tag, __a,
1517 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
1518 { }
1519
1520 template<typename _Alloc, typename _U1, typename _U2,
1521 _ExplicitCtor<true, const _U1&, const _U2&> = false>
1522 explicit
1523 _GLIBCXX20_CONSTEXPR
1524 tuple(allocator_arg_t __tag, const _Alloc& __a,
1525 const tuple<_U1, _U2>& __in)
1526 : _Inherited(__tag, __a,
1527 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
1528 { }
1529
1530 template<typename _Alloc, typename _U1, typename _U2,
1531 _ImplicitCtor<true, _U1, _U2> = true>
1532 _GLIBCXX20_CONSTEXPR
1533 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
1534 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
1535 { }
1536
1537 template<typename _Alloc, typename _U1, typename _U2,
1538 _ExplicitCtor<true, _U1, _U2> = false>
1539 explicit
1540 _GLIBCXX20_CONSTEXPR
1541 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
1542 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
1543 { }
1544
1545#if __cplusplus > 202002L
1546 template<typename _Alloc, typename _U1, typename _U2>
1547 requires __constructible<_U1&, _U2&>
1548 explicit(!__convertible<_U1&, _U2&>)
1549 constexpr
1550 tuple(allocator_arg_t __tag, const _Alloc& __a,
1551 tuple<_U1, _U2>& __in)
1552 : _Inherited(__tag, __a,
1553 static_cast<_Tuple_impl<0, _U1, _U2>&>(__in))
1554 { }
1555
1556 template<typename _Alloc, typename _U1, typename _U2>
1557 requires __constructible<const _U1, const _U2>
1558 explicit(!__convertible<const _U1, const _U2>)
1559 constexpr
1560 tuple(allocator_arg_t __tag, const _Alloc& __a,
1561 const tuple<_U1, _U2>&& __in)
1562 : _Inherited(__tag, __a,
1563 static_cast<const _Tuple_impl<0, _U1, _U2>&&>(__in))
1564 { }
1565#endif // C++23
1566
1567 template<typename _Alloc, typename _U1, typename _U2,
1568 _ImplicitCtor<true, const _U1&, const _U2&> = true>
1569 _GLIBCXX20_CONSTEXPR
1570 tuple(allocator_arg_t __tag, const _Alloc& __a,
1571 const pair<_U1, _U2>& __in)
1572 : _Inherited(__tag, __a, __in.first, __in.second) { }
1573
1574 template<typename _Alloc, typename _U1, typename _U2,
1575 _ExplicitCtor<true, const _U1&, const _U2&> = false>
1576 explicit
1577 _GLIBCXX20_CONSTEXPR
1578 tuple(allocator_arg_t __tag, const _Alloc& __a,
1579 const pair<_U1, _U2>& __in)
1580 : _Inherited(__tag, __a, __in.first, __in.second) { }
1581
1582 template<typename _Alloc, typename _U1, typename _U2,
1583 _ImplicitCtor<true, _U1, _U2> = true>
1584 _GLIBCXX20_CONSTEXPR
1585 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
1586 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
1587 std::forward<_U2>(__in.second)) { }
1588
1589 template<typename _Alloc, typename _U1, typename _U2,
1590 _ExplicitCtor<true, _U1, _U2> = false>
1591 explicit
1592 _GLIBCXX20_CONSTEXPR
1593 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
1594 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
1595 std::forward<_U2>(__in.second)) { }
1596
1597#if __cplusplus > 202002L
1598 template<typename _Alloc, typename _U1, typename _U2>
1599 requires __constructible<_U1&, _U2&>
1600 explicit(!__convertible<_U1&, _U2&>)
1601 constexpr
1602 tuple(allocator_arg_t __tag, const _Alloc& __a,
1603 pair<_U1, _U2>& __in)
1604 : _Inherited(__tag, __a, __in.first, __in.second) { }
1605
1606 template<typename _Alloc, typename _U1, typename _U2>
1607 requires __constructible<const _U1, const _U2>
1608 explicit(!__convertible<const _U1, const _U2>)
1609 constexpr
1610 tuple(allocator_arg_t __tag, const _Alloc& __a, const pair<_U1, _U2>&& __in)
1611 : _Inherited(__tag, __a, std::forward<const _U1>(__in.first),
1612 std::forward<const _U2>(__in.second)) { }
1613#endif // C++23
1614
1615 // Tuple assignment.
1616
1617 _GLIBCXX20_CONSTEXPR
1618 tuple&
1619 operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
1620 const tuple&,
1621 const __nonesuch&> __in)
1622 noexcept(__nothrow_assignable<const _T1&, const _T2&>())
1623 {
1624 this->_M_assign(__in);
1625 return *this;
1626 }
1627
1628 _GLIBCXX20_CONSTEXPR
1629 tuple&
1630 operator=(__conditional_t<__assignable<_T1, _T2>(),
1631 tuple&&,
1632 __nonesuch&&> __in)
1633 noexcept(__nothrow_assignable<_T1, _T2>())
1634 {
1635 this->_M_assign(std::move(__in));
1636 return *this;
1637 }
1638
1639 template<typename _U1, typename _U2>
1640 _GLIBCXX20_CONSTEXPR
1641 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
1642 operator=(const tuple<_U1, _U2>& __in)
1643 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1644 {
1645 this->_M_assign(__in);
1646 return *this;
1647 }
1648
1649 template<typename _U1, typename _U2>
1650 _GLIBCXX20_CONSTEXPR
1651 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
1652 operator=(tuple<_U1, _U2>&& __in)
1653 noexcept(__nothrow_assignable<_U1, _U2>())
1654 {
1655 this->_M_assign(std::move(__in));
1656 return *this;
1657 }
1658
1659#if __cplusplus > 202002L
1660 constexpr const tuple&
1661 operator=(const tuple& __in) const
1662 requires is_copy_assignable_v<const _T1> && is_copy_assignable_v<const _T2>
1663 {
1664 this->_M_assign(__in);
1665 return *this;
1666 }
1667
1668 constexpr const tuple&
1669 operator=(tuple&& __in) const
1670 requires is_assignable_v<const _T1&, _T1> && is_assignable_v<const _T2, _T2>
1671 {
1672 this->_M_assign(std::move(__in));
1673 return *this;
1674 }
1675
1676 template<typename _U1, typename _U2>
1677 constexpr const tuple&
1678 operator=(const tuple<_U1, _U2>& __in) const
1679 requires is_assignable_v<const _T1&, const _U1&>
1680 && is_assignable_v<const _T2&, const _U2&>
1681 {
1682 this->_M_assign(__in);
1683 return *this;
1684 }
1685
1686 template<typename _U1, typename _U2>
1687 constexpr const tuple&
1688 operator=(tuple<_U1, _U2>&& __in) const
1689 requires is_assignable_v<const _T1&, _U1>
1690 && is_assignable_v<const _T2&, _U2>
1691 {
1692 this->_M_assign(std::move(__in));
1693 return *this;
1694 }
1695#endif // C++23
1696
1697 template<typename _U1, typename _U2>
1698 _GLIBCXX20_CONSTEXPR
1699 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
1700 operator=(const pair<_U1, _U2>& __in)
1701 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1702 {
1703 this->_M_head(*this) = __in.first;
1704 this->_M_tail(*this)._M_head(*this) = __in.second;
1705 return *this;
1706 }
1707
1708 template<typename _U1, typename _U2>
1709 _GLIBCXX20_CONSTEXPR
1710 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
1711 operator=(pair<_U1, _U2>&& __in)
1712 noexcept(__nothrow_assignable<_U1, _U2>())
1713 {
1714 this->_M_head(*this) = std::forward<_U1>(__in.first);
1715 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
1716 return *this;
1717 }
1718
1719#if __cplusplus > 202002L
1720 template<typename _U1, typename _U2>
1721 constexpr const tuple&
1722 operator=(const pair<_U1, _U2>& __in) const
1723 requires is_assignable_v<const _T1&, const _U1&>
1724 && is_assignable_v<const _T2&, const _U2&>
1725 {
1726 this->_M_head(*this) = __in.first;
1727 this->_M_tail(*this)._M_head(*this) = __in.second;
1728 return *this;
1729 }
1730
1731 template<typename _U1, typename _U2>
1732 constexpr const tuple&
1733 operator=(pair<_U1, _U2>&& __in) const
1734 requires is_assignable_v<const _T1&, _U1>
1735 && is_assignable_v<const _T2&, _U2>
1736 {
1737 this->_M_head(*this) = std::forward<_U1>(__in.first);
1738 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
1739 return *this;
1740 }
1741#endif // C++23
1742
1743 _GLIBCXX20_CONSTEXPR
1744 void
1745 swap(tuple& __in)
1746 noexcept(__and_<__is_nothrow_swappable<_T1>,
1747 __is_nothrow_swappable<_T2>>::value)
1748 { _Inherited::_M_swap(__in); }
1749
1750#if __cplusplus > 202002L
1751 constexpr void
1752 swap(const tuple& __in) const
1753 noexcept(__and_v<__is_nothrow_swappable<const _T1>,
1754 __is_nothrow_swappable<const _T2>>)
1755 requires is_swappable_v<const _T1> && is_swappable_v<const _T2>
1756 { _Inherited::_M_swap(__in); }
1757#endif // C++23
1758 };
1759
1760
1761 /// class tuple_size
1762 template<typename... _Elements>
1763 struct tuple_size<tuple<_Elements...>>
1764 : public integral_constant<size_t, sizeof...(_Elements)> { };
1765
1766#if __cplusplus >= 201703L
1767 template<typename... _Types>
1768 inline constexpr size_t tuple_size_v<tuple<_Types...>>
1769 = sizeof...(_Types);
1770
1771 template<typename... _Types>
1772 inline constexpr size_t tuple_size_v<const tuple<_Types...>>
1773 = sizeof...(_Types);
1774#endif
1775
1776 /// Trait to get the Ith element type from a tuple.
1777 template<size_t __i, typename... _Types>
1778 struct tuple_element<__i, tuple<_Types...>>
1779 {
1780 static_assert(__i < sizeof...(_Types), "tuple index must be in range");
1781
1782 using type = typename _Nth_type<__i, _Types...>::type;
1783 };
1784
1785 template<size_t __i, typename _Head, typename... _Tail>
1786 constexpr _Head&
1787 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
1788 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
1789
1790 template<size_t __i, typename _Head, typename... _Tail>
1791 constexpr const _Head&
1792 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
1793 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
1794
1795 // Deleted overload to improve diagnostics for invalid indices
1796 template<size_t __i, typename... _Types>
1797 __enable_if_t<(__i >= sizeof...(_Types))>
1798 __get_helper(const tuple<_Types...>&) = delete;
1799
1800 /// Return a reference to the ith element of a tuple.
1801 template<size_t __i, typename... _Elements>
1802 constexpr __tuple_element_t<__i, tuple<_Elements...>>&
1803 get(tuple<_Elements...>& __t) noexcept
1804 { return std::__get_helper<__i>(__t); }
1805
1806 /// Return a const reference to the ith element of a const tuple.
1807 template<size_t __i, typename... _Elements>
1808 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
1809 get(const tuple<_Elements...>& __t) noexcept
1810 { return std::__get_helper<__i>(__t); }
1811
1812 /// Return an rvalue reference to the ith element of a tuple rvalue.
1813 template<size_t __i, typename... _Elements>
1814 constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
1815 get(tuple<_Elements...>&& __t) noexcept
1816 {
1817 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
1818 return std::forward<__element_type>(std::__get_helper<__i>(__t));
1819 }
1820
1821 /// Return a const rvalue reference to the ith element of a const tuple rvalue.
1822 template<size_t __i, typename... _Elements>
1823 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
1824 get(const tuple<_Elements...>&& __t) noexcept
1825 {
1826 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
1827 return std::forward<const __element_type>(std::__get_helper<__i>(__t));
1828 }
1829
1830 /// @cond undocumented
1831 // Deleted overload chosen for invalid indices.
1832 template<size_t __i, typename... _Elements>
1833 constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
1834 get(const tuple<_Elements...>&) = delete;
1835 /// @endcond
1836
1837#if __cplusplus >= 201402L
1838
1839#define __cpp_lib_tuples_by_type 201304L
1840
1841 /// Return a reference to the unique element of type _Tp of a tuple.
1842 template <typename _Tp, typename... _Types>
1843 constexpr _Tp&
1844 get(tuple<_Types...>& __t) noexcept
1845 {
1846 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1847 static_assert(__idx < sizeof...(_Types),
1848 "the type T in std::get<T> must occur exactly once in the tuple");
1849 return std::__get_helper<__idx>(__t);
1850 }
1851
1852 /// Return a reference to the unique element of type _Tp of a tuple rvalue.
1853 template <typename _Tp, typename... _Types>
1854 constexpr _Tp&&
1855 get(tuple<_Types...>&& __t) noexcept
1856 {
1857 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1858 static_assert(__idx < sizeof...(_Types),
1859 "the type T in std::get<T> must occur exactly once in the tuple");
1860 return std::forward<_Tp>(std::__get_helper<__idx>(__t));
1861 }
1862
1863 /// Return a const reference to the unique element of type _Tp of a tuple.
1864 template <typename _Tp, typename... _Types>
1865 constexpr const _Tp&
1866 get(const tuple<_Types...>& __t) noexcept
1867 {
1868 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1869 static_assert(__idx < sizeof...(_Types),
1870 "the type T in std::get<T> must occur exactly once in the tuple");
1871 return std::__get_helper<__idx>(__t);
1872 }
1873
1874 /// Return a const reference to the unique element of type _Tp of
1875 /// a const tuple rvalue.
1876 template <typename _Tp, typename... _Types>
1877 constexpr const _Tp&&
1878 get(const tuple<_Types...>&& __t) noexcept
1879 {
1880 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1881 static_assert(__idx < sizeof...(_Types),
1882 "the type T in std::get<T> must occur exactly once in the tuple");
1883 return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
1884 }
1885#endif
1886
1887 // This class performs the comparison operations on tuples
1888 template<typename _Tp, typename _Up, size_t __i, size_t __size>
1889 struct __tuple_compare
1890 {
1891 static constexpr bool
1892 __eq(const _Tp& __t, const _Up& __u)
1893 {
1894 return bool(std::get<__i>(__t) == std::get<__i>(__u))
1895 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
1896 }
1897
1898 static constexpr bool
1899 __less(const _Tp& __t, const _Up& __u)
1900 {
1901 return bool(std::get<__i>(__t) < std::get<__i>(__u))
1902 || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
1903 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
1904 }
1905 };
1906
1907 template<typename _Tp, typename _Up, size_t __size>
1908 struct __tuple_compare<_Tp, _Up, __size, __size>
1909 {
1910 static constexpr bool
1911 __eq(const _Tp&, const _Up&) { return true; }
1912
1913 static constexpr bool
1914 __less(const _Tp&, const _Up&) { return false; }
1915 };
1916
1917 template<typename... _TElements, typename... _UElements>
1918 constexpr bool
1919 operator==(const tuple<_TElements...>& __t,
1920 const tuple<_UElements...>& __u)
1921 {
1922 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
1923 "tuple objects can only be compared if they have equal sizes.");
1924 using __compare = __tuple_compare<tuple<_TElements...>,
1925 tuple<_UElements...>,
1926 0, sizeof...(_TElements)>;
1927 return __compare::__eq(__t, __u);
1928 }
1929
1930#if __cpp_lib_three_way_comparison
1931 template<typename _Cat, typename _Tp, typename _Up>
1932 constexpr _Cat
1933 __tuple_cmp(const _Tp&, const _Up&, index_sequence<>)
1934 { return _Cat::equivalent; }
1935
1936 template<typename _Cat, typename _Tp, typename _Up,
1937 size_t _Idx0, size_t... _Idxs>
1938 constexpr _Cat
1939 __tuple_cmp(const _Tp& __t, const _Up& __u,
1940 index_sequence<_Idx0, _Idxs...>)
1941 {
1942 auto __c
1943 = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u));
1944 if (__c != 0)
1945 return __c;
1946 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>());
1947 }
1948
1949 template<typename... _Tps, typename... _Ups>
1950 constexpr
1951 common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
1952 operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
1953 {
1954 using _Cat
1955 = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
1956 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
1957 }
1958#else
1959 template<typename... _TElements, typename... _UElements>
1960 constexpr bool
1961 operator<(const tuple<_TElements...>& __t,
1962 const tuple<_UElements...>& __u)
1963 {
1964 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
1965 "tuple objects can only be compared if they have equal sizes.");
1966 using __compare = __tuple_compare<tuple<_TElements...>,
1967 tuple<_UElements...>,
1968 0, sizeof...(_TElements)>;
1969 return __compare::__less(__t, __u);
1970 }
1971
1972 template<typename... _TElements, typename... _UElements>
1973 constexpr bool
1974 operator!=(const tuple<_TElements...>& __t,
1975 const tuple<_UElements...>& __u)
1976 { return !(__t == __u); }
1977
1978 template<typename... _TElements, typename... _UElements>
1979 constexpr bool
1980 operator>(const tuple<_TElements...>& __t,
1981 const tuple<_UElements...>& __u)
1982 { return __u < __t; }
1983
1984 template<typename... _TElements, typename... _UElements>
1985 constexpr bool
1986 operator<=(const tuple<_TElements...>& __t,
1987 const tuple<_UElements...>& __u)
1988 { return !(__u < __t); }
1989
1990 template<typename... _TElements, typename... _UElements>
1991 constexpr bool
1992 operator>=(const tuple<_TElements...>& __t,
1993 const tuple<_UElements...>& __u)
1994 { return !(__t < __u); }
1995#endif // three_way_comparison
1996
1997 // NB: DR 705.
1998 /// Create a tuple containing copies of the arguments
1999 template<typename... _Elements>
2000 constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
2001 make_tuple(_Elements&&... __args)
2002 {
2003 typedef tuple<typename __decay_and_strip<_Elements>::__type...>
2004 __result_type;
2005 return __result_type(std::forward<_Elements>(__args)...);
2006 }
2007
2008 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2009 // 2275. Why is forward_as_tuple not constexpr?
2010 /// Create a tuple of lvalue or rvalue references to the arguments
2011 template<typename... _Elements>
2012 constexpr tuple<_Elements&&...>
2013 forward_as_tuple(_Elements&&... __args) noexcept
2014 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2015
2016 // Declarations of std::array and its std::get overloads, so that
2017 // std::tuple_cat can use them if <tuple> is included before <array>.
2018
2019 template<typename _Tp, size_t _Nm> struct array;
2020
2021 template<size_t _Int, typename _Tp, size_t _Nm>
2022 constexpr _Tp&
2023 get(array<_Tp, _Nm>&) noexcept;
2024
2025 template<size_t _Int, typename _Tp, size_t _Nm>
2026 constexpr _Tp&&
2027 get(array<_Tp, _Nm>&&) noexcept;
2028
2029 template<size_t _Int, typename _Tp, size_t _Nm>
2030 constexpr const _Tp&
2031 get(const array<_Tp, _Nm>&) noexcept;
2032
2033 template<size_t _Int, typename _Tp, size_t _Nm>
2034 constexpr const _Tp&&
2035 get(const array<_Tp, _Nm>&&) noexcept;
2036
2037 /// @cond undocumented
2038 template<size_t, typename, typename, size_t>
2039 struct __make_tuple_impl;
2040
2041 template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
2042 struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
2043 : __make_tuple_impl<_Idx + 1,
2044 tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
2045 _Tuple, _Nm>
2046 { };
2047
2048 template<size_t _Nm, typename _Tuple, typename... _Tp>
2049 struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
2050 {
2051 typedef tuple<_Tp...> __type;
2052 };
2053
2054 template<typename _Tuple>
2055 struct __do_make_tuple
2056 : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
2057 { };
2058
2059 // Returns the std::tuple equivalent of a tuple-like type.
2060 template<typename _Tuple>
2061 struct __make_tuple
2062 : public __do_make_tuple<__remove_cvref_t<_Tuple>>
2063 { };
2064
2065 // Combines several std::tuple's into a single one.
2066 template<typename...>
2067 struct __combine_tuples;
2068
2069 template<>
2070 struct __combine_tuples<>
2071 {
2072 typedef tuple<> __type;
2073 };
2074
2075 template<typename... _Ts>
2076 struct __combine_tuples<tuple<_Ts...>>
2077 {
2078 typedef tuple<_Ts...> __type;
2079 };
2080
2081 template<typename... _T1s, typename... _T2s, typename... _Rem>
2082 struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
2083 {
2084 typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
2085 _Rem...>::__type __type;
2086 };
2087
2088 // Computes the result type of tuple_cat given a set of tuple-like types.
2089 template<typename... _Tpls>
2090 struct __tuple_cat_result
2091 {
2092 typedef typename __combine_tuples
2093 <typename __make_tuple<_Tpls>::__type...>::__type __type;
2094 };
2095
2096 // Helper to determine the index set for the first tuple-like
2097 // type of a given set.
2098 template<typename...>
2099 struct __make_1st_indices;
2100
2101 template<>
2102 struct __make_1st_indices<>
2103 {
2104 typedef _Index_tuple<> __type;
2105 };
2106
2107 template<typename _Tp, typename... _Tpls>
2108 struct __make_1st_indices<_Tp, _Tpls...>
2109 {
2110 typedef typename _Build_index_tuple<tuple_size<
2111 typename remove_reference<_Tp>::type>::value>::__type __type;
2112 };
2113
2114 // Performs the actual concatenation by step-wise expanding tuple-like
2115 // objects into the elements, which are finally forwarded into the
2116 // result tuple.
2117 template<typename _Ret, typename _Indices, typename... _Tpls>
2118 struct __tuple_concater;
2119
2120 template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2121 struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2122 {
2123 template<typename... _Us>
2124 static constexpr _Ret
2125 _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2126 {
2127 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2128 typedef __tuple_concater<_Ret, __idx, _Tpls...> __next;
2129 return __next::_S_do(std::forward<_Tpls>(__tps)...,
2130 std::forward<_Us>(__us)...,
2131 std::get<_Is>(std::forward<_Tp>(__tp))...);
2132 }
2133 };
2134
2135 template<typename _Ret>
2136 struct __tuple_concater<_Ret, _Index_tuple<>>
2137 {
2138 template<typename... _Us>
2139 static constexpr _Ret
2140 _S_do(_Us&&... __us)
2141 {
2142 return _Ret(std::forward<_Us>(__us)...);
2143 }
2144 };
2145
2146 template<typename... _Tps>
2147 struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2148 { };
2149 /// @endcond
2150
2151 /// Create a `tuple` containing all elements from multiple tuple-like objects
2152 template<typename... _Tpls, typename = typename
2153 enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2154 constexpr auto
2155 tuple_cat(_Tpls&&... __tpls)
2156 -> typename __tuple_cat_result<_Tpls...>::__type
2157 {
2158 typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2159 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2160 typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2161 return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2162 }
2163
2164 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2165 // 2301. Why is tie not constexpr?
2166 /// Return a tuple of lvalue references bound to the arguments
2167 template<typename... _Elements>
2168 constexpr tuple<_Elements&...>
2169 tie(_Elements&... __args) noexcept
2170 { return tuple<_Elements&...>(__args...); }
2171
2172 /// Exchange the values of two tuples
2173 template<typename... _Elements>
2174 _GLIBCXX20_CONSTEXPR
2175 inline
2176#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2177 // Constrained free swap overload, see p0185r1
2178 typename enable_if<__and_<__is_swappable<_Elements>...>::value
2179 >::type
2180#else
2181 void
2182#endif
2183 swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
2184 noexcept(noexcept(__x.swap(__y)))
2185 { __x.swap(__y); }
2186
2187#if __cplusplus > 202002L
2188 template<typename... _Elements>
2189 requires (is_swappable_v<const _Elements> && ...)
2190 constexpr void
2191 swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2192 noexcept(noexcept(__x.swap(__y)))
2193 { __x.swap(__y); }
2194#endif // C++23
2195
2196#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2197 /// Exchange the values of two const tuples (if const elements can be swapped)
2198 template<typename... _Elements>
2199 _GLIBCXX20_CONSTEXPR
2200 typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2201 swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2202#endif
2203
2204 // A class (and instance) which can be used in 'tie' when an element
2205 // of a tuple is not required.
2206 // _GLIBCXX14_CONSTEXPR
2207 // 2933. PR for LWG 2773 could be clearer
2208 struct _Swallow_assign
2209 {
2210 template<class _Tp>
2211 _GLIBCXX14_CONSTEXPR const _Swallow_assign&
2212 operator=(const _Tp&) const
2213 { return *this; }
2214 };
2215
2216 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2217 // 2773. Making std::ignore constexpr
2218 /** Used with `std::tie` to ignore an element of a tuple
2219 *
2220 * When using `std::tie` to assign the elements of a tuple to variables,
2221 * unwanted elements can be ignored by using `std::ignore`. For example:
2222 *
2223 * ```
2224 * int x, y;
2225 * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3);
2226 * ```
2227 *
2228 * This assignment will perform `x=1; std::ignore=2; y=3;` which results
2229 * in the second element being ignored.
2230 *
2231 * @since C++11
2232 */
2233 _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{};
2234
2235 /// Partial specialization for tuples
2236 template<typename... _Types, typename _Alloc>
2237 struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2238
2239 // See stl_pair.h...
2240 /** "piecewise construction" using a tuple of arguments for each member.
2241 *
2242 * @param __first Arguments for the first member of the pair.
2243 * @param __second Arguments for the second member of the pair.
2244 *
2245 * The elements of each tuple will be used as the constructor arguments
2246 * for the data members of the pair.
2247 */
2248 template<class _T1, class _T2>
2249 template<typename... _Args1, typename... _Args2>
2250 _GLIBCXX20_CONSTEXPR
2251 inline
2252 pair<_T1, _T2>::
2253 pair(piecewise_construct_t,
2254 tuple<_Args1...> __first, tuple<_Args2...> __second)
2255 : pair(__first, __second,
2256 typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2257 typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2258 { }
2259
2260 template<class _T1, class _T2>
2261 template<typename... _Args1, size_t... _Indexes1,
2262 typename... _Args2, size_t... _Indexes2>
2263 _GLIBCXX20_CONSTEXPR inline
2264 pair<_T1, _T2>::
2265 pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2266 _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2267 : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2268 second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2269 { }
2270
2271#if __cplusplus >= 201703L
2272
2273 // Unpack a std::tuple into a type trait and use its value.
2274 // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2275 // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2276 // Otherwise the result is false (because we don't know if std::get throws).
2277 template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2278 inline constexpr bool __unpack_std_tuple = false;
2279
2280 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2281 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2282 = _Trait<_Tp, _Up...>::value;
2283
2284 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2285 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2286 = _Trait<_Tp, _Up&...>::value;
2287
2288 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2289 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2290 = _Trait<_Tp, const _Up...>::value;
2291
2292 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2293 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2294 = _Trait<_Tp, const _Up&...>::value;
2295
2296# define __cpp_lib_apply 201603L
2297
2298 template <typename _Fn, typename _Tuple, size_t... _Idx>
2299 constexpr decltype(auto)
2300 __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2301 {
2302 return std::__invoke(std::forward<_Fn>(__f),
2303 std::get<_Idx>(std::forward<_Tuple>(__t))...);
2304 }
2305
2306 template <typename _Fn, typename _Tuple>
2307 constexpr decltype(auto)
2308 apply(_Fn&& __f, _Tuple&& __t)
2309 noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2310 {
2311 using _Indices
2312 = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2313 return std::__apply_impl(std::forward<_Fn>(__f),
2314 std::forward<_Tuple>(__t),
2315 _Indices{});
2316 }
2317
2318#define __cpp_lib_make_from_tuple 201606L
2319
2320 template <typename _Tp, typename _Tuple, size_t... _Idx>
2321 constexpr _Tp
2322 __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
2323 { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
2324
2325 template <typename _Tp, typename _Tuple>
2326 constexpr _Tp
2327 make_from_tuple(_Tuple&& __t)
2328 noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
2329 {
2330 constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
2331#if __has_builtin(__reference_constructs_from_temporary)
2332 if constexpr (__n == 1)
2333 {
2334 using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
2335 static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
2336 }
2337#endif
2338 return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
2339 make_index_sequence<__n>{});
2340 }
2341#endif // C++17
2342
2343#if __cplusplus > 202002L
2344 template<typename... _TTypes, typename... _UTypes,
2345 template<typename> class _TQual, template<typename> class _UQual>
2346 requires requires { typename tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; }
2347 struct basic_common_reference<tuple<_TTypes...>, tuple<_UTypes...>, _TQual, _UQual>
2348 { using type = tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; };
2349
2350 template<typename... _TTypes, typename... _UTypes>
2351 requires requires { typename tuple<common_type_t<_TTypes, _UTypes>...>; }
2352 struct common_type<tuple<_TTypes...>, tuple<_UTypes...>>
2353 { using type = tuple<common_type_t<_TTypes, _UTypes>...>; };
2354#endif // C++23
2355
2356 /// @}
2357
2358_GLIBCXX_END_NAMESPACE_VERSION
2359} // namespace std
2360
2361#endif // C++11
2362
2363#endif // _GLIBCXX_TUPLE