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 __tag, 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 __tag, 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 __tag, 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 __tag, 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 __tag, 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 __tag, 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 __tag, 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 __tag, 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, bool _NotEmpty = (sizeof...(_Elements) >= 1),
975 _ImplicitCtor<_NotEmpty, const _Elements&...> = true>
976 _GLIBCXX20_CONSTEXPR
977 tuple(allocator_arg_t __tag, const _Alloc& __a,
978 const _Elements&... __elements)
979 : _Inherited(__tag, __a, __elements...) { }
980
981 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1),
982 _ExplicitCtor<_NotEmpty, const _Elements&...> = false>
983 _GLIBCXX20_CONSTEXPR
984 explicit
985 tuple(allocator_arg_t __tag, const _Alloc& __a,
986 const _Elements&... __elements)
987 : _Inherited(__tag, __a, __elements...) { }
988
989 template<typename _Alloc, typename... _UElements,
990 bool _Valid = __valid_args<_UElements...>(),
991 _ImplicitCtor<_Valid, _UElements...> = true>
992 _GLIBCXX20_CONSTEXPR
993 tuple(allocator_arg_t __tag, const _Alloc& __a,
994 _UElements&&... __elements)
995 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
996 { }
997
998 template<typename _Alloc, typename... _UElements,
999 bool _Valid = __valid_args<_UElements...>(),
1000 _ExplicitCtor<_Valid, _UElements...> = false>
1001 _GLIBCXX20_CONSTEXPR
1002 explicit
1003 tuple(allocator_arg_t __tag, const _Alloc& __a,
1004 _UElements&&... __elements)
1005 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
1006 { }
1007
1008 template<typename _Alloc>
1009 _GLIBCXX20_CONSTEXPR
1010 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1011 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1012
1013 template<typename _Alloc>
1014 _GLIBCXX20_CONSTEXPR
1015 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1016 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1017
1018 template<typename _Alloc, typename... _UElements,
1019 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1020 && !__use_other_ctor<const tuple<_UElements...>&>(),
1021 _ImplicitCtor<_Valid, const _UElements&...> = true>
1022 _GLIBCXX20_CONSTEXPR
1023 tuple(allocator_arg_t __tag, const _Alloc& __a,
1024 const tuple<_UElements...>& __in)
1025 : _Inherited(__tag, __a,
1026 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1027 { }
1028
1029 template<typename _Alloc, typename... _UElements,
1030 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1031 && !__use_other_ctor<const tuple<_UElements...>&>(),
1032 _ExplicitCtor<_Valid, const _UElements&...> = false>
1033 _GLIBCXX20_CONSTEXPR
1034 explicit
1035 tuple(allocator_arg_t __tag, const _Alloc& __a,
1036 const tuple<_UElements...>& __in)
1037 : _Inherited(__tag, __a,
1038 static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
1039 { }
1040
1041 template<typename _Alloc, typename... _UElements,
1042 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1043 && !__use_other_ctor<tuple<_UElements...>&&>(),
1044 _ImplicitCtor<_Valid, _UElements...> = true>
1045 _GLIBCXX20_CONSTEXPR
1046 tuple(allocator_arg_t __tag, const _Alloc& __a,
1047 tuple<_UElements...>&& __in)
1048 : _Inherited(__tag, __a,
1049 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1050 { }
1051
1052 template<typename _Alloc, typename... _UElements,
1053 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements))
1054 && !__use_other_ctor<tuple<_UElements...>&&>(),
1055 _ExplicitCtor<_Valid, _UElements...> = false>
1056 _GLIBCXX20_CONSTEXPR
1057 explicit
1058 tuple(allocator_arg_t __tag, const _Alloc& __a,
1059 tuple<_UElements...>&& __in)
1060 : _Inherited(__tag, __a,
1061 static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
1062 { }
1063
1064#if __cplusplus > 202002L
1065 template<typename _Alloc, typename... _UElements>
1066 requires (sizeof...(_Elements) == sizeof...(_UElements))
1067 && (!__use_other_ctor<tuple<_UElements...>&>())
1068 && __constructible<_UElements&...>
1069 explicit(!__convertible<_UElements&...>)
1070 constexpr
1071 tuple(allocator_arg_t __tag, const _Alloc& __a,
1072 tuple<_UElements...>& __in)
1073 : _Inherited(__tag, __a,
1074 static_cast<_Tuple_impl<0, _UElements...>&>(__in))
1075 { }
1076
1077 template<typename _Alloc, typename... _UElements>
1078 requires (sizeof...(_Elements) == sizeof...(_UElements))
1079 && (!__use_other_ctor<const tuple<_UElements...>>())
1080 && __constructible<const _UElements...>
1081 explicit(!__convertible<const _UElements...>)
1082 constexpr
1083 tuple(allocator_arg_t __tag, const _Alloc& __a,
1084 const tuple<_UElements...>&& __in)
1085 : _Inherited(__tag, __a,
1086 static_cast<const _Tuple_impl<0, _UElements...>&&>(__in))
1087 { }
1088#endif // C++23
1089
1090 // tuple assignment
1091
1092 _GLIBCXX20_CONSTEXPR
1093 tuple&
1094 operator=(__conditional_t<__assignable<const _Elements&...>(),
1095 const tuple&,
1096 const __nonesuch&> __in)
1097 noexcept(__nothrow_assignable<const _Elements&...>())
1098 {
1099 this->_M_assign(__in);
1100 return *this;
1101 }
1102
1103 _GLIBCXX20_CONSTEXPR
1104 tuple&
1105 operator=(__conditional_t<__assignable<_Elements...>(),
1106 tuple&&,
1107 __nonesuch&&> __in)
1108 noexcept(__nothrow_assignable<_Elements...>())
1109 {
1110 this->_M_assign(std::move(__in));
1111 return *this;
1112 }
1113
1114 template<typename... _UElements>
1115 _GLIBCXX20_CONSTEXPR
1116 __enable_if_t<__assignable<const _UElements&...>(), tuple&>
1117 operator=(const tuple<_UElements...>& __in)
1118 noexcept(__nothrow_assignable<const _UElements&...>())
1119 {
1120 this->_M_assign(__in);
1121 return *this;
1122 }
1123
1124 template<typename... _UElements>
1125 _GLIBCXX20_CONSTEXPR
1126 __enable_if_t<__assignable<_UElements...>(), tuple&>
1127 operator=(tuple<_UElements...>&& __in)
1128 noexcept(__nothrow_assignable<_UElements...>())
1129 {
1130 this->_M_assign(std::move(__in));
1131 return *this;
1132 }
1133
1134#if __cplusplus > 202002L
1135 constexpr const tuple&
1136 operator=(const tuple& __in) const
1137 requires (is_copy_assignable_v<const _Elements> && ...)
1138 {
1139 this->_M_assign(__in);
1140 return *this;
1141 }
1142
1143 constexpr const tuple&
1144 operator=(tuple&& __in) const
1145 requires (is_assignable_v<const _Elements&, _Elements> && ...)
1146 {
1147 this->_M_assign(std::move(__in));
1148 return *this;
1149 }
1150
1151 template<typename... _UElements>
1152 constexpr const tuple&
1153 operator=(const tuple<_UElements...>& __in) const
1154 requires (sizeof...(_Elements) == sizeof...(_UElements))
1155 && (is_assignable_v<const _Elements&, const _UElements&> && ...)
1156 {
1157 this->_M_assign(__in);
1158 return *this;
1159 }
1160
1161 template<typename... _UElements>
1162 constexpr const tuple&
1163 operator=(tuple<_UElements...>&& __in) const
1164 requires (sizeof...(_Elements) == sizeof...(_UElements))
1165 && (is_assignable_v<const _Elements&, _UElements> && ...)
1166 {
1167 this->_M_assign(std::move(__in));
1168 return *this;
1169 }
1170#endif // C++23
1171
1172 // tuple swap
1173 _GLIBCXX20_CONSTEXPR
1174 void
1175 swap(tuple& __in)
1176 noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
1177 { _Inherited::_M_swap(__in); }
1178
1179#if __cplusplus > 202002L
1180 // As an extension, we constrain the const swap member function in order
1181 // to continue accepting explicit instantiation of tuples whose elements
1182 // are not all const swappable. Without this constraint, such an
1183 // explicit instantiation would also instantiate the ill-formed body of
1184 // this function and yield a hard error. This constraint shouldn't
1185 // affect the behavior of valid programs.
1186 constexpr void
1187 swap(const tuple& __in) const
1188 noexcept(__and_v<__is_nothrow_swappable<const _Elements>...>)
1189 requires (is_swappable_v<const _Elements> && ...)
1190 { _Inherited::_M_swap(__in); }
1191#endif // C++23
1192 };
1193
1194#if __cpp_deduction_guides >= 201606
1195 template<typename... _UTypes>
1196 tuple(_UTypes...) -> tuple<_UTypes...>;
1197 template<typename _T1, typename _T2>
1198 tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>;
1199 template<typename _Alloc, typename... _UTypes>
1200 tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>;
1201 template<typename _Alloc, typename _T1, typename _T2>
1202 tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>;
1203 template<typename _Alloc, typename... _UTypes>
1204 tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>;
1205#endif
1206
1207 // Explicit specialization, zero-element tuple.
1208 template<>
1209 class tuple<>
1210 {
1211 public:
1212 _GLIBCXX20_CONSTEXPR
1213 void swap(tuple&) noexcept { /* no-op */ }
1214#if __cplusplus > 202002L
1215 constexpr void swap(const tuple&) const noexcept { /* no-op */ }
1216#endif
1217 // We need the default since we're going to define no-op
1218 // allocator constructors.
1219 tuple() = default;
1220 // No-op allocator constructors.
1221 template<typename _Alloc>
1222 _GLIBCXX20_CONSTEXPR
1223 tuple(allocator_arg_t, const _Alloc&) noexcept { }
1224 template<typename _Alloc>
1225 _GLIBCXX20_CONSTEXPR
1226 tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
1227 };
1228
1229 /// Partial specialization, 2-element tuple.
1230 /// Includes construction and assignment from a pair.
1231 template<typename _T1, typename _T2>
1232 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
1233 {
1234 typedef _Tuple_impl<0, _T1, _T2> _Inherited;
1235
1236 // Constraint for non-explicit default constructor
1237 template<bool _Dummy, typename _U1, typename _U2>
1238 using _ImplicitDefaultCtor = __enable_if_t<
1239 _TupleConstraints<_Dummy, _U1, _U2>::
1240 __is_implicitly_default_constructible(),
1241 bool>;
1242
1243 // Constraint for explicit default constructor
1244 template<bool _Dummy, typename _U1, typename _U2>
1245 using _ExplicitDefaultCtor = __enable_if_t<
1246 _TupleConstraints<_Dummy, _U1, _U2>::
1247 __is_explicitly_default_constructible(),
1248 bool>;
1249
1250 template<bool _Dummy>
1251 using _TCC = _TupleConstraints<_Dummy, _T1, _T2>;
1252
1253 // Constraint for non-explicit constructors
1254 template<bool _Cond, typename _U1, typename _U2>
1255 using _ImplicitCtor = __enable_if_t<
1256 _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(),
1257 bool>;
1258
1259 // Constraint for non-explicit constructors
1260 template<bool _Cond, typename _U1, typename _U2>
1261 using _ExplicitCtor = __enable_if_t<
1262 _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(),
1263 bool>;
1264
1265 template<typename _U1, typename _U2>
1266 static constexpr bool __assignable()
1267 {
1268 return __and_<is_assignable<_T1&, _U1>,
1269 is_assignable<_T2&, _U2>>::value;
1270 }
1271
1272 template<typename _U1, typename _U2>
1273 static constexpr bool __nothrow_assignable()
1274 {
1275 return __and_<is_nothrow_assignable<_T1&, _U1>,
1276 is_nothrow_assignable<_T2&, _U2>>::value;
1277 }
1278
1279 template<typename _U1, typename _U2>
1280 static constexpr bool __nothrow_constructible()
1281 {
1282 return __and_<is_nothrow_constructible<_T1, _U1>,
1283 is_nothrow_constructible<_T2, _U2>>::value;
1284 }
1285
1286 static constexpr bool __nothrow_default_constructible()
1287 {
1288 return __and_<is_nothrow_default_constructible<_T1>,
1289 is_nothrow_default_constructible<_T2>>::value;
1290 }
1291
1292 template<typename _U1>
1293 static constexpr bool __is_alloc_arg()
1294 { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; }
1295
1296#if __cplusplus > 202002L
1297 template<typename _U1, typename _U2>
1298 static constexpr bool __constructible
1299 = _TCC<true>::template __constructible<_U1, _U2>::value;
1300
1301 template<typename _U1, typename _U2>
1302 static constexpr bool __convertible
1303 = _TCC<true>::template __convertible<_U1, _U2>::value;
1304#endif // C++23
1305
1306 public:
1307 template<bool _Dummy = true,
1308 _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true>
1309 constexpr
1310 tuple()
1311 noexcept(__nothrow_default_constructible())
1312 : _Inherited() { }
1313
1314 template<bool _Dummy = true,
1315 _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false>
1316 explicit constexpr
1317 tuple()
1318 noexcept(__nothrow_default_constructible())
1319 : _Inherited() { }
1320
1321 template<bool _Dummy = true,
1322 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
1323 constexpr
1324 tuple(const _T1& __a1, const _T2& __a2)
1325 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
1326 : _Inherited(__a1, __a2) { }
1327
1328 template<bool _Dummy = true,
1329 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
1330 explicit constexpr
1331 tuple(const _T1& __a1, const _T2& __a2)
1332 noexcept(__nothrow_constructible<const _T1&, const _T2&>())
1333 : _Inherited(__a1, __a2) { }
1334
1335 template<typename _U1, typename _U2,
1336 _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true>
1337 constexpr
1338 tuple(_U1&& __a1, _U2&& __a2)
1339 noexcept(__nothrow_constructible<_U1, _U2>())
1340 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
1341
1342 template<typename _U1, typename _U2,
1343 _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false>
1344 explicit 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 constexpr tuple(const tuple&) = default;
1350
1351 constexpr tuple(tuple&&) = default;
1352
1353 template<typename _U1, typename _U2,
1354 _ImplicitCtor<true, const _U1&, const _U2&> = true>
1355 constexpr
1356 tuple(const tuple<_U1, _U2>& __in)
1357 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1358 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
1359
1360 template<typename _U1, typename _U2,
1361 _ExplicitCtor<true, const _U1&, const _U2&> = false>
1362 explicit 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 _ImplicitCtor<true, _U1, _U2> = true>
1369 constexpr
1370 tuple(tuple<_U1, _U2>&& __in)
1371 noexcept(__nothrow_constructible<_U1, _U2>())
1372 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
1373
1374 template<typename _U1, typename _U2,
1375 _ExplicitCtor<true, _U1, _U2> = false>
1376 explicit 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#if __cplusplus > 202002L
1382 template<typename _U1, typename _U2>
1383 requires __constructible<_U1&, _U2&>
1384 explicit(!__convertible<_U1&, _U2&>)
1385 constexpr
1386 tuple(tuple<_U1, _U2>& __in)
1387 noexcept(__nothrow_constructible<_U1&, _U2&>())
1388 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&>(__in)) { }
1389
1390 template<typename _U1, typename _U2>
1391 requires __constructible<const _U1, const _U2>
1392 explicit(!__convertible<const _U1, const _U2>)
1393 constexpr
1394 tuple(const tuple<_U1, _U2>&& __in)
1395 noexcept(__nothrow_constructible<const _U1, const _U2>())
1396 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&&>(__in)) { }
1397#endif // C++23
1398
1399 template<typename _U1, typename _U2,
1400 _ImplicitCtor<true, const _U1&, const _U2&> = true>
1401 constexpr
1402 tuple(const pair<_U1, _U2>& __in)
1403 noexcept(__nothrow_constructible<const _U1&, const _U2&>())
1404 : _Inherited(__in.first, __in.second) { }
1405
1406 template<typename _U1, typename _U2,
1407 _ExplicitCtor<true, const _U1&, const _U2&> = false>
1408 explicit 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 _ImplicitCtor<true, _U1, _U2> = true>
1415 constexpr
1416 tuple(pair<_U1, _U2>&& __in)
1417 noexcept(__nothrow_constructible<_U1, _U2>())
1418 : _Inherited(std::forward<_U1>(__in.first),
1419 std::forward<_U2>(__in.second)) { }
1420
1421 template<typename _U1, typename _U2,
1422 _ExplicitCtor<true, _U1, _U2> = false>
1423 explicit constexpr
1424 tuple(pair<_U1, _U2>&& __in)
1425 noexcept(__nothrow_constructible<_U1, _U2>())
1426 : _Inherited(std::forward<_U1>(__in.first),
1427 std::forward<_U2>(__in.second)) { }
1428
1429#if __cplusplus > 202002L
1430 template<typename _U1, typename _U2>
1431 requires __constructible<_U1&, _U2&>
1432 explicit(!__convertible<_U1&, _U2&>)
1433 constexpr
1434 tuple(pair<_U1, _U2>& __in)
1435 noexcept(__nothrow_constructible<_U1&, _U2&>())
1436 : _Inherited(__in.first, __in.second) { }
1437
1438 template<typename _U1, typename _U2>
1439 requires __constructible<const _U1, const _U2>
1440 explicit(!__convertible<const _U1, const _U2>)
1441 constexpr
1442 tuple(const pair<_U1, _U2>&& __in)
1443 noexcept(__nothrow_constructible<const _U1, const _U2>())
1444 : _Inherited(std::forward<const _U1>(__in.first),
1445 std::forward<const _U2>(__in.second)) { }
1446#endif // C++23
1447
1448 // Allocator-extended constructors.
1449
1450 template<typename _Alloc,
1451 _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true>
1452 _GLIBCXX20_CONSTEXPR
1453 tuple(allocator_arg_t __tag, const _Alloc& __a)
1454 : _Inherited(__tag, __a) { }
1455
1456 template<typename _Alloc, bool _Dummy = true,
1457 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true>
1458 _GLIBCXX20_CONSTEXPR
1459 tuple(allocator_arg_t __tag, const _Alloc& __a,
1460 const _T1& __a1, const _T2& __a2)
1461 : _Inherited(__tag, __a, __a1, __a2) { }
1462
1463 template<typename _Alloc, bool _Dummy = true,
1464 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false>
1465 explicit
1466 _GLIBCXX20_CONSTEXPR
1467 tuple(allocator_arg_t __tag, const _Alloc& __a,
1468 const _T1& __a1, const _T2& __a2)
1469 : _Inherited(__tag, __a, __a1, __a2) { }
1470
1471 template<typename _Alloc, typename _U1, typename _U2,
1472 _ImplicitCtor<true, _U1, _U2> = true>
1473 _GLIBCXX20_CONSTEXPR
1474 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
1475 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
1476 std::forward<_U2>(__a2)) { }
1477
1478 template<typename _Alloc, typename _U1, typename _U2,
1479 _ExplicitCtor<true, _U1, _U2> = false>
1480 explicit
1481 _GLIBCXX20_CONSTEXPR
1482 tuple(allocator_arg_t __tag, const _Alloc& __a,
1483 _U1&& __a1, _U2&& __a2)
1484 : _Inherited(__tag, __a, std::forward<_U1>(__a1),
1485 std::forward<_U2>(__a2)) { }
1486
1487 template<typename _Alloc>
1488 _GLIBCXX20_CONSTEXPR
1489 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
1490 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
1491
1492 template<typename _Alloc>
1493 _GLIBCXX20_CONSTEXPR
1494 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
1495 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
1496
1497 template<typename _Alloc, typename _U1, typename _U2,
1498 _ImplicitCtor<true, const _U1&, const _U2&> = true>
1499 _GLIBCXX20_CONSTEXPR
1500 tuple(allocator_arg_t __tag, const _Alloc& __a,
1501 const tuple<_U1, _U2>& __in)
1502 : _Inherited(__tag, __a,
1503 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
1504 { }
1505
1506 template<typename _Alloc, typename _U1, typename _U2,
1507 _ExplicitCtor<true, const _U1&, const _U2&> = false>
1508 explicit
1509 _GLIBCXX20_CONSTEXPR
1510 tuple(allocator_arg_t __tag, const _Alloc& __a,
1511 const tuple<_U1, _U2>& __in)
1512 : _Inherited(__tag, __a,
1513 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
1514 { }
1515
1516 template<typename _Alloc, typename _U1, typename _U2,
1517 _ImplicitCtor<true, _U1, _U2> = true>
1518 _GLIBCXX20_CONSTEXPR
1519 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
1520 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
1521 { }
1522
1523 template<typename _Alloc, typename _U1, typename _U2,
1524 _ExplicitCtor<true, _U1, _U2> = false>
1525 explicit
1526 _GLIBCXX20_CONSTEXPR
1527 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
1528 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
1529 { }
1530
1531#if __cplusplus > 202002L
1532 template<typename _Alloc, typename _U1, typename _U2>
1533 requires __constructible<_U1&, _U2&>
1534 explicit(!__convertible<_U1&, _U2&>)
1535 constexpr
1536 tuple(allocator_arg_t __tag, const _Alloc& __a,
1537 tuple<_U1, _U2>& __in)
1538 : _Inherited(__tag, __a,
1539 static_cast<_Tuple_impl<0, _U1, _U2>&>(__in))
1540 { }
1541
1542 template<typename _Alloc, typename _U1, typename _U2>
1543 requires __constructible<const _U1, const _U2>
1544 explicit(!__convertible<const _U1, const _U2>)
1545 constexpr
1546 tuple(allocator_arg_t __tag, const _Alloc& __a,
1547 const tuple<_U1, _U2>&& __in)
1548 : _Inherited(__tag, __a,
1549 static_cast<const _Tuple_impl<0, _U1, _U2>&&>(__in))
1550 { }
1551#endif // C++23
1552
1553 template<typename _Alloc, typename _U1, typename _U2,
1554 _ImplicitCtor<true, const _U1&, const _U2&> = true>
1555 _GLIBCXX20_CONSTEXPR
1556 tuple(allocator_arg_t __tag, const _Alloc& __a,
1557 const pair<_U1, _U2>& __in)
1558 : _Inherited(__tag, __a, __in.first, __in.second) { }
1559
1560 template<typename _Alloc, typename _U1, typename _U2,
1561 _ExplicitCtor<true, const _U1&, const _U2&> = false>
1562 explicit
1563 _GLIBCXX20_CONSTEXPR
1564 tuple(allocator_arg_t __tag, const _Alloc& __a,
1565 const pair<_U1, _U2>& __in)
1566 : _Inherited(__tag, __a, __in.first, __in.second) { }
1567
1568 template<typename _Alloc, typename _U1, typename _U2,
1569 _ImplicitCtor<true, _U1, _U2> = true>
1570 _GLIBCXX20_CONSTEXPR
1571 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
1572 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
1573 std::forward<_U2>(__in.second)) { }
1574
1575 template<typename _Alloc, typename _U1, typename _U2,
1576 _ExplicitCtor<true, _U1, _U2> = false>
1577 explicit
1578 _GLIBCXX20_CONSTEXPR
1579 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
1580 : _Inherited(__tag, __a, std::forward<_U1>(__in.first),
1581 std::forward<_U2>(__in.second)) { }
1582
1583#if __cplusplus > 202002L
1584 template<typename _Alloc, typename _U1, typename _U2>
1585 requires __constructible<_U1&, _U2&>
1586 explicit(!__convertible<_U1&, _U2&>)
1587 constexpr
1588 tuple(allocator_arg_t __tag, const _Alloc& __a,
1589 pair<_U1, _U2>& __in)
1590 : _Inherited(__tag, __a, __in.first, __in.second) { }
1591
1592 template<typename _Alloc, typename _U1, typename _U2>
1593 requires __constructible<const _U1, const _U2>
1594 explicit(!__convertible<const _U1, const _U2>)
1595 constexpr
1596 tuple(allocator_arg_t __tag, const _Alloc& __a, const pair<_U1, _U2>&& __in)
1597 : _Inherited(__tag, __a, std::forward<const _U1>(__in.first),
1598 std::forward<const _U2>(__in.second)) { }
1599#endif // C++23
1600
1601 // Tuple assignment.
1602
1603 _GLIBCXX20_CONSTEXPR
1604 tuple&
1605 operator=(__conditional_t<__assignable<const _T1&, const _T2&>(),
1606 const tuple&,
1607 const __nonesuch&> __in)
1608 noexcept(__nothrow_assignable<const _T1&, const _T2&>())
1609 {
1610 this->_M_assign(__in);
1611 return *this;
1612 }
1613
1614 _GLIBCXX20_CONSTEXPR
1615 tuple&
1616 operator=(__conditional_t<__assignable<_T1, _T2>(),
1617 tuple&&,
1618 __nonesuch&&> __in)
1619 noexcept(__nothrow_assignable<_T1, _T2>())
1620 {
1621 this->_M_assign(std::move(__in));
1622 return *this;
1623 }
1624
1625 template<typename _U1, typename _U2>
1626 _GLIBCXX20_CONSTEXPR
1627 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
1628 operator=(const tuple<_U1, _U2>& __in)
1629 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1630 {
1631 this->_M_assign(__in);
1632 return *this;
1633 }
1634
1635 template<typename _U1, typename _U2>
1636 _GLIBCXX20_CONSTEXPR
1637 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
1638 operator=(tuple<_U1, _U2>&& __in)
1639 noexcept(__nothrow_assignable<_U1, _U2>())
1640 {
1641 this->_M_assign(std::move(__in));
1642 return *this;
1643 }
1644
1645#if __cplusplus > 202002L
1646 constexpr const tuple&
1647 operator=(const tuple& __in) const
1648 requires is_copy_assignable_v<const _T1> && is_copy_assignable_v<const _T2>
1649 {
1650 this->_M_assign(__in);
1651 return *this;
1652 }
1653
1654 constexpr const tuple&
1655 operator=(tuple&& __in) const
1656 requires is_assignable_v<const _T1&, _T1> && is_assignable_v<const _T2, _T2>
1657 {
1658 this->_M_assign(std::move(__in));
1659 return *this;
1660 }
1661
1662 template<typename _U1, typename _U2>
1663 constexpr const tuple&
1664 operator=(const tuple<_U1, _U2>& __in) const
1665 requires is_assignable_v<const _T1&, const _U1&>
1666 && is_assignable_v<const _T2&, const _U2&>
1667 {
1668 this->_M_assign(__in);
1669 return *this;
1670 }
1671
1672 template<typename _U1, typename _U2>
1673 constexpr const tuple&
1674 operator=(tuple<_U1, _U2>&& __in) const
1675 requires is_assignable_v<const _T1&, _U1>
1676 && is_assignable_v<const _T2&, _U2>
1677 {
1678 this->_M_assign(std::move(__in));
1679 return *this;
1680 }
1681#endif // C++23
1682
1683 template<typename _U1, typename _U2>
1684 _GLIBCXX20_CONSTEXPR
1685 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&>
1686 operator=(const pair<_U1, _U2>& __in)
1687 noexcept(__nothrow_assignable<const _U1&, const _U2&>())
1688 {
1689 this->_M_head(*this) = __in.first;
1690 this->_M_tail(*this)._M_head(*this) = __in.second;
1691 return *this;
1692 }
1693
1694 template<typename _U1, typename _U2>
1695 _GLIBCXX20_CONSTEXPR
1696 __enable_if_t<__assignable<_U1, _U2>(), tuple&>
1697 operator=(pair<_U1, _U2>&& __in)
1698 noexcept(__nothrow_assignable<_U1, _U2>())
1699 {
1700 this->_M_head(*this) = std::forward<_U1>(__in.first);
1701 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
1702 return *this;
1703 }
1704
1705#if __cplusplus > 202002L
1706 template<typename _U1, typename _U2>
1707 constexpr const tuple&
1708 operator=(const pair<_U1, _U2>& __in) const
1709 requires is_assignable_v<const _T1&, const _U1&>
1710 && is_assignable_v<const _T2&, const _U2&>
1711 {
1712 this->_M_head(*this) = __in.first;
1713 this->_M_tail(*this)._M_head(*this) = __in.second;
1714 return *this;
1715 }
1716
1717 template<typename _U1, typename _U2>
1718 constexpr const tuple&
1719 operator=(pair<_U1, _U2>&& __in) const
1720 requires is_assignable_v<const _T1&, _U1>
1721 && is_assignable_v<const _T2&, _U2>
1722 {
1723 this->_M_head(*this) = std::forward<_U1>(__in.first);
1724 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second);
1725 return *this;
1726 }
1727#endif // C++23
1728
1729 _GLIBCXX20_CONSTEXPR
1730 void
1731 swap(tuple& __in)
1732 noexcept(__and_<__is_nothrow_swappable<_T1>,
1733 __is_nothrow_swappable<_T2>>::value)
1734 { _Inherited::_M_swap(__in); }
1735
1736#if __cplusplus > 202002L
1737 constexpr void
1738 swap(const tuple& __in) const
1739 noexcept(__and_v<__is_nothrow_swappable<const _T1>,
1740 __is_nothrow_swappable<const _T2>>)
1741 requires is_swappable_v<const _T1> && is_swappable_v<const _T2>
1742 { _Inherited::_M_swap(__in); }
1743#endif // C++23
1744 };
1745
1746
1747 /// class tuple_size
1748 template<typename... _Elements>
1749 struct tuple_size<tuple<_Elements...>>
1750 : public integral_constant<size_t, sizeof...(_Elements)> { };
1751
1752#if __cplusplus >= 201703L
1753 template<typename... _Types>
1754 inline constexpr size_t tuple_size_v<tuple<_Types...>>
1755 = sizeof...(_Types);
1756
1757 template<typename... _Types>
1758 inline constexpr size_t tuple_size_v<const tuple<_Types...>>
1759 = sizeof...(_Types);
1760#endif
1761
1762 /// Trait to get the Ith element type from a tuple.
1763 template<size_t __i, typename... _Types>
1764 struct tuple_element<__i, tuple<_Types...>>
1765 {
1766 static_assert(__i < sizeof...(_Types), "tuple index must be in range");
1767
1768 using type = typename _Nth_type<__i, _Types...>::type;
1769 };
1770
1771 template<size_t __i, typename _Head, typename... _Tail>
1772 constexpr _Head&
1773 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
1774 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
1775
1776 template<size_t __i, typename _Head, typename... _Tail>
1777 constexpr const _Head&
1778 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept
1779 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); }
1780
1781 // Deleted overload to improve diagnostics for invalid indices
1782 template<size_t __i, typename... _Types>
1783 __enable_if_t<(__i >= sizeof...(_Types))>
1784 __get_helper(const tuple<_Types...>&) = delete;
1785
1786 /// Return a reference to the ith element of a tuple.
1787 template<size_t __i, typename... _Elements>
1788 constexpr __tuple_element_t<__i, tuple<_Elements...>>&
1789 get(tuple<_Elements...>& __t) noexcept
1790 { return std::__get_helper<__i>(__t); }
1791
1792 /// Return a const reference to the ith element of a const tuple.
1793 template<size_t __i, typename... _Elements>
1794 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&
1795 get(const tuple<_Elements...>& __t) noexcept
1796 { return std::__get_helper<__i>(__t); }
1797
1798 /// Return an rvalue reference to the ith element of a tuple rvalue.
1799 template<size_t __i, typename... _Elements>
1800 constexpr __tuple_element_t<__i, tuple<_Elements...>>&&
1801 get(tuple<_Elements...>&& __t) noexcept
1802 {
1803 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
1804 return std::forward<__element_type>(std::__get_helper<__i>(__t));
1805 }
1806
1807 /// Return a const rvalue reference to the ith element of a const tuple rvalue.
1808 template<size_t __i, typename... _Elements>
1809 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&&
1810 get(const tuple<_Elements...>&& __t) noexcept
1811 {
1812 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type;
1813 return std::forward<const __element_type>(std::__get_helper<__i>(__t));
1814 }
1815
1816 /// @cond undocumented
1817 // Deleted overload chosen for invalid indices.
1818 template<size_t __i, typename... _Elements>
1819 constexpr __enable_if_t<(__i >= sizeof...(_Elements))>
1820 get(const tuple<_Elements...>&) = delete;
1821 /// @endcond
1822
1823#if __cplusplus >= 201402L
1824
1825#define __cpp_lib_tuples_by_type 201304L
1826
1827 /// Return a reference to the unique element of type _Tp of a tuple.
1828 template <typename _Tp, typename... _Types>
1829 constexpr _Tp&
1830 get(tuple<_Types...>& __t) noexcept
1831 {
1832 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1833 static_assert(__idx < sizeof...(_Types),
1834 "the type T in std::get<T> must occur exactly once in the tuple");
1835 return std::__get_helper<__idx>(__t);
1836 }
1837
1838 /// Return a reference to the unique element of type _Tp of a tuple rvalue.
1839 template <typename _Tp, typename... _Types>
1840 constexpr _Tp&&
1841 get(tuple<_Types...>&& __t) noexcept
1842 {
1843 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1844 static_assert(__idx < sizeof...(_Types),
1845 "the type T in std::get<T> must occur exactly once in the tuple");
1846 return std::forward<_Tp>(std::__get_helper<__idx>(__t));
1847 }
1848
1849 /// Return a const reference to the unique element of type _Tp of a tuple.
1850 template <typename _Tp, typename... _Types>
1851 constexpr const _Tp&
1852 get(const tuple<_Types...>& __t) noexcept
1853 {
1854 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1855 static_assert(__idx < sizeof...(_Types),
1856 "the type T in std::get<T> must occur exactly once in the tuple");
1857 return std::__get_helper<__idx>(__t);
1858 }
1859
1860 /// Return a const reference to the unique element of type _Tp of
1861 /// a const tuple rvalue.
1862 template <typename _Tp, typename... _Types>
1863 constexpr const _Tp&&
1864 get(const tuple<_Types...>&& __t) noexcept
1865 {
1866 constexpr size_t __idx = __find_uniq_type_in_pack<_Tp, _Types...>();
1867 static_assert(__idx < sizeof...(_Types),
1868 "the type T in std::get<T> must occur exactly once in the tuple");
1869 return std::forward<const _Tp>(std::__get_helper<__idx>(__t));
1870 }
1871#endif
1872
1873 // This class performs the comparison operations on tuples
1874 template<typename _Tp, typename _Up, size_t __i, size_t __size>
1875 struct __tuple_compare
1876 {
1877 static constexpr bool
1878 __eq(const _Tp& __t, const _Up& __u)
1879 {
1880 return bool(std::get<__i>(__t) == std::get<__i>(__u))
1881 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u);
1882 }
1883
1884 static constexpr bool
1885 __less(const _Tp& __t, const _Up& __u)
1886 {
1887 return bool(std::get<__i>(__t) < std::get<__i>(__u))
1888 || (!bool(std::get<__i>(__u) < std::get<__i>(__t))
1889 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u));
1890 }
1891 };
1892
1893 template<typename _Tp, typename _Up, size_t __size>
1894 struct __tuple_compare<_Tp, _Up, __size, __size>
1895 {
1896 static constexpr bool
1897 __eq(const _Tp&, const _Up&) { return true; }
1898
1899 static constexpr bool
1900 __less(const _Tp&, const _Up&) { return false; }
1901 };
1902
1903 template<typename... _TElements, typename... _UElements>
1904 constexpr bool
1905 operator==(const tuple<_TElements...>& __t,
1906 const tuple<_UElements...>& __u)
1907 {
1908 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
1909 "tuple objects can only be compared if they have equal sizes.");
1910 using __compare = __tuple_compare<tuple<_TElements...>,
1911 tuple<_UElements...>,
1912 0, sizeof...(_TElements)>;
1913 return __compare::__eq(__t, __u);
1914 }
1915
1916#if __cpp_lib_three_way_comparison
1917 template<typename _Cat, typename _Tp, typename _Up>
1918 constexpr _Cat
1919 __tuple_cmp(const _Tp&, const _Up&, index_sequence<>)
1920 { return _Cat::equivalent; }
1921
1922 template<typename _Cat, typename _Tp, typename _Up,
1923 size_t _Idx0, size_t... _Idxs>
1924 constexpr _Cat
1925 __tuple_cmp(const _Tp& __t, const _Up& __u,
1926 index_sequence<_Idx0, _Idxs...>)
1927 {
1928 auto __c
1929 = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u));
1930 if (__c != 0)
1931 return __c;
1932 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>());
1933 }
1934
1935 template<typename... _Tps, typename... _Ups>
1936 constexpr
1937 common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>
1938 operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u)
1939 {
1940 using _Cat
1941 = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>;
1942 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>());
1943 }
1944#else
1945 template<typename... _TElements, typename... _UElements>
1946 constexpr bool
1947 operator<(const tuple<_TElements...>& __t,
1948 const tuple<_UElements...>& __u)
1949 {
1950 static_assert(sizeof...(_TElements) == sizeof...(_UElements),
1951 "tuple objects can only be compared if they have equal sizes.");
1952 using __compare = __tuple_compare<tuple<_TElements...>,
1953 tuple<_UElements...>,
1954 0, sizeof...(_TElements)>;
1955 return __compare::__less(__t, __u);
1956 }
1957
1958 template<typename... _TElements, typename... _UElements>
1959 constexpr bool
1960 operator!=(const tuple<_TElements...>& __t,
1961 const tuple<_UElements...>& __u)
1962 { return !(__t == __u); }
1963
1964 template<typename... _TElements, typename... _UElements>
1965 constexpr bool
1966 operator>(const tuple<_TElements...>& __t,
1967 const tuple<_UElements...>& __u)
1968 { return __u < __t; }
1969
1970 template<typename... _TElements, typename... _UElements>
1971 constexpr bool
1972 operator<=(const tuple<_TElements...>& __t,
1973 const tuple<_UElements...>& __u)
1974 { return !(__u < __t); }
1975
1976 template<typename... _TElements, typename... _UElements>
1977 constexpr bool
1978 operator>=(const tuple<_TElements...>& __t,
1979 const tuple<_UElements...>& __u)
1980 { return !(__t < __u); }
1981#endif // three_way_comparison
1982
1983 // NB: DR 705.
1984 /// Create a tuple containing copies of the arguments
1985 template<typename... _Elements>
1986 constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
1987 make_tuple(_Elements&&... __args)
1988 {
1989 typedef tuple<typename __decay_and_strip<_Elements>::__type...>
1990 __result_type;
1991 return __result_type(std::forward<_Elements>(__args)...);
1992 }
1993
1994 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1995 // 2275. Why is forward_as_tuple not constexpr?
1996 /// Create a tuple of lvalue or rvalue references to the arguments
1997 template<typename... _Elements>
1998 constexpr tuple<_Elements&&...>
1999 forward_as_tuple(_Elements&&... __args) noexcept
2000 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
2001
2002 // Declarations of std::array and its std::get overloads, so that
2003 // std::tuple_cat can use them if <tuple> is included before <array>.
2004
2005 template<typename _Tp, size_t _Nm> struct array;
2006
2007 template<size_t _Int, typename _Tp, size_t _Nm>
2008 constexpr _Tp&
2009 get(array<_Tp, _Nm>&) noexcept;
2010
2011 template<size_t _Int, typename _Tp, size_t _Nm>
2012 constexpr _Tp&&
2013 get(array<_Tp, _Nm>&&) noexcept;
2014
2015 template<size_t _Int, typename _Tp, size_t _Nm>
2016 constexpr const _Tp&
2017 get(const array<_Tp, _Nm>&) noexcept;
2018
2019 template<size_t _Int, typename _Tp, size_t _Nm>
2020 constexpr const _Tp&&
2021 get(const array<_Tp, _Nm>&&) noexcept;
2022
2023 /// @cond undocumented
2024 template<size_t, typename, typename, size_t>
2025 struct __make_tuple_impl;
2026
2027 template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm>
2028 struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm>
2029 : __make_tuple_impl<_Idx + 1,
2030 tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>,
2031 _Tuple, _Nm>
2032 { };
2033
2034 template<size_t _Nm, typename _Tuple, typename... _Tp>
2035 struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm>
2036 {
2037 typedef tuple<_Tp...> __type;
2038 };
2039
2040 template<typename _Tuple>
2041 struct __do_make_tuple
2042 : __make_tuple_impl<0, tuple<>, _Tuple, tuple_size<_Tuple>::value>
2043 { };
2044
2045 // Returns the std::tuple equivalent of a tuple-like type.
2046 template<typename _Tuple>
2047 struct __make_tuple
2048 : public __do_make_tuple<__remove_cvref_t<_Tuple>>
2049 { };
2050
2051 // Combines several std::tuple's into a single one.
2052 template<typename...>
2053 struct __combine_tuples;
2054
2055 template<>
2056 struct __combine_tuples<>
2057 {
2058 typedef tuple<> __type;
2059 };
2060
2061 template<typename... _Ts>
2062 struct __combine_tuples<tuple<_Ts...>>
2063 {
2064 typedef tuple<_Ts...> __type;
2065 };
2066
2067 template<typename... _T1s, typename... _T2s, typename... _Rem>
2068 struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...>
2069 {
2070 typedef typename __combine_tuples<tuple<_T1s..., _T2s...>,
2071 _Rem...>::__type __type;
2072 };
2073
2074 // Computes the result type of tuple_cat given a set of tuple-like types.
2075 template<typename... _Tpls>
2076 struct __tuple_cat_result
2077 {
2078 typedef typename __combine_tuples
2079 <typename __make_tuple<_Tpls>::__type...>::__type __type;
2080 };
2081
2082 // Helper to determine the index set for the first tuple-like
2083 // type of a given set.
2084 template<typename...>
2085 struct __make_1st_indices;
2086
2087 template<>
2088 struct __make_1st_indices<>
2089 {
2090 typedef _Index_tuple<> __type;
2091 };
2092
2093 template<typename _Tp, typename... _Tpls>
2094 struct __make_1st_indices<_Tp, _Tpls...>
2095 {
2096 typedef typename _Build_index_tuple<tuple_size<
2097 typename remove_reference<_Tp>::type>::value>::__type __type;
2098 };
2099
2100 // Performs the actual concatenation by step-wise expanding tuple-like
2101 // objects into the elements, which are finally forwarded into the
2102 // result tuple.
2103 template<typename _Ret, typename _Indices, typename... _Tpls>
2104 struct __tuple_concater;
2105
2106 template<typename _Ret, size_t... _Is, typename _Tp, typename... _Tpls>
2107 struct __tuple_concater<_Ret, _Index_tuple<_Is...>, _Tp, _Tpls...>
2108 {
2109 template<typename... _Us>
2110 static constexpr _Ret
2111 _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us)
2112 {
2113 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2114 typedef __tuple_concater<_Ret, __idx, _Tpls...> __next;
2115 return __next::_S_do(std::forward<_Tpls>(__tps)...,
2116 std::forward<_Us>(__us)...,
2117 std::get<_Is>(std::forward<_Tp>(__tp))...);
2118 }
2119 };
2120
2121 template<typename _Ret>
2122 struct __tuple_concater<_Ret, _Index_tuple<>>
2123 {
2124 template<typename... _Us>
2125 static constexpr _Ret
2126 _S_do(_Us&&... __us)
2127 {
2128 return _Ret(std::forward<_Us>(__us)...);
2129 }
2130 };
2131
2132 template<typename... _Tps>
2133 struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
2134 { };
2135 /// @endcond
2136
2137 /// Create a `tuple` containing all elements from multiple tuple-like objects
2138 template<typename... _Tpls, typename = typename
2139 enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type>
2140 constexpr auto
2141 tuple_cat(_Tpls&&... __tpls)
2142 -> typename __tuple_cat_result<_Tpls...>::__type
2143 {
2144 typedef typename __tuple_cat_result<_Tpls...>::__type __ret;
2145 typedef typename __make_1st_indices<_Tpls...>::__type __idx;
2146 typedef __tuple_concater<__ret, __idx, _Tpls...> __concater;
2147 return __concater::_S_do(std::forward<_Tpls>(__tpls)...);
2148 }
2149
2150 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2151 // 2301. Why is tie not constexpr?
2152 /// Return a tuple of lvalue references bound to the arguments
2153 template<typename... _Elements>
2154 constexpr tuple<_Elements&...>
2155 tie(_Elements&... __args) noexcept
2156 { return tuple<_Elements&...>(__args...); }
2157
2158 /// Exchange the values of two tuples
2159 template<typename... _Elements>
2160 _GLIBCXX20_CONSTEXPR
2161 inline
2162#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2163 // Constrained free swap overload, see p0185r1
2164 typename enable_if<__and_<__is_swappable<_Elements>...>::value
2165 >::type
2166#else
2167 void
2168#endif
2169 swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y)
2170 noexcept(noexcept(__x.swap(__y)))
2171 { __x.swap(__y); }
2172
2173#if __cplusplus > 202002L
2174 template<typename... _Elements>
2175 requires (is_swappable_v<const _Elements> && ...)
2176 constexpr void
2177 swap(const tuple<_Elements...>& __x, const tuple<_Elements...>& __y)
2178 noexcept(noexcept(__x.swap(__y)))
2179 { __x.swap(__y); }
2180#endif // C++23
2181
2182#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
2183 /// Exchange the values of two const tuples (if const elements can be swapped)
2184 template<typename... _Elements>
2185 _GLIBCXX20_CONSTEXPR
2186 typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type
2187 swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete;
2188#endif
2189
2190 // A class (and instance) which can be used in 'tie' when an element
2191 // of a tuple is not required.
2192 // _GLIBCXX14_CONSTEXPR
2193 // 2933. PR for LWG 2773 could be clearer
2194 struct _Swallow_assign
2195 {
2196 template<class _Tp>
2197 _GLIBCXX14_CONSTEXPR const _Swallow_assign&
2198 operator=(const _Tp&) const
2199 { return *this; }
2200 };
2201
2202 // _GLIBCXX_RESOLVE_LIB_DEFECTS
2203 // 2773. Making std::ignore constexpr
2204 /** Used with `std::tie` to ignore an element of a tuple
2205 *
2206 * When using `std::tie` to assign the elements of a tuple to variables,
2207 * unwanted elements can be ignored by using `std::ignore`. For example:
2208 *
2209 * ```
2210 * int x, y;
2211 * std::tie(x, std::ignore, y) = std::make_tuple(1, 2, 3);
2212 * ```
2213 *
2214 * This assignment will perform `x=1; std::ignore=2; y=3;` which results
2215 * in the second element being ignored.
2216 *
2217 * @since C++11
2218 */
2219 _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{};
2220
2221 /// Partial specialization for tuples
2222 template<typename... _Types, typename _Alloc>
2223 struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { };
2224
2225 // See stl_pair.h...
2226 /** "piecewise construction" using a tuple of arguments for each member.
2227 *
2228 * @param __first Arguments for the first member of the pair.
2229 * @param __second Arguments for the second member of the pair.
2230 *
2231 * The elements of each tuple will be used as the constructor arguments
2232 * for the data members of the pair.
2233 */
2234 template<class _T1, class _T2>
2235 template<typename... _Args1, typename... _Args2>
2236 _GLIBCXX20_CONSTEXPR
2237 inline
2238 pair<_T1, _T2>::
2239 pair(piecewise_construct_t,
2240 tuple<_Args1...> __first, tuple<_Args2...> __second)
2241 : pair(__first, __second,
2242 typename _Build_index_tuple<sizeof...(_Args1)>::__type(),
2243 typename _Build_index_tuple<sizeof...(_Args2)>::__type())
2244 { }
2245
2246 template<class _T1, class _T2>
2247 template<typename... _Args1, size_t... _Indexes1,
2248 typename... _Args2, size_t... _Indexes2>
2249 _GLIBCXX20_CONSTEXPR inline
2250 pair<_T1, _T2>::
2251 pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2,
2252 _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>)
2253 : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...),
2254 second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
2255 { }
2256
2257#if __cplusplus >= 201703L
2258
2259 // Unpack a std::tuple into a type trait and use its value.
2260 // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value.
2261 // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value.
2262 // Otherwise the result is false (because we don't know if std::get throws).
2263 template<template<typename...> class _Trait, typename _Tp, typename _Tuple>
2264 inline constexpr bool __unpack_std_tuple = false;
2265
2266 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2267 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>>
2268 = _Trait<_Tp, _Up...>::value;
2269
2270 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2271 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&>
2272 = _Trait<_Tp, _Up&...>::value;
2273
2274 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2275 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>>
2276 = _Trait<_Tp, const _Up...>::value;
2277
2278 template<template<typename...> class _Trait, typename _Tp, typename... _Up>
2279 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&>
2280 = _Trait<_Tp, const _Up&...>::value;
2281
2282# define __cpp_lib_apply 201603L
2283
2284 template <typename _Fn, typename _Tuple, size_t... _Idx>
2285 constexpr decltype(auto)
2286 __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>)
2287 {
2288 return std::__invoke(std::forward<_Fn>(__f),
2289 std::get<_Idx>(std::forward<_Tuple>(__t))...);
2290 }
2291
2292 template <typename _Fn, typename _Tuple>
2293 constexpr decltype(auto)
2294 apply(_Fn&& __f, _Tuple&& __t)
2295 noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>)
2296 {
2297 using _Indices
2298 = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>;
2299 return std::__apply_impl(std::forward<_Fn>(__f),
2300 std::forward<_Tuple>(__t),
2301 _Indices{});
2302 }
2303
2304#define __cpp_lib_make_from_tuple 201606L
2305
2306 template <typename _Tp, typename _Tuple, size_t... _Idx>
2307 constexpr _Tp
2308 __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>)
2309 { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); }
2310
2311 template <typename _Tp, typename _Tuple>
2312 constexpr _Tp
2313 make_from_tuple(_Tuple&& __t)
2314 noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>)
2315 {
2316 constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>;
2317#if __has_builtin(__reference_constructs_from_temporary)
2318 if constexpr (__n == 1)
2319 {
2320 using _Elt = decltype(std::get<0>(std::declval<_Tuple>()));
2321 static_assert(!__reference_constructs_from_temporary(_Tp, _Elt));
2322 }
2323#endif
2324 return __make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
2325 make_index_sequence<__n>{});
2326 }
2327#endif // C++17
2328
2329#if __cplusplus > 202002L
2330 template<typename... _TTypes, typename... _UTypes,
2331 template<typename> class _TQual, template<typename> class _UQual>
2332 requires requires { typename tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; }
2333 struct basic_common_reference<tuple<_TTypes...>, tuple<_UTypes...>, _TQual, _UQual>
2334 { using type = tuple<common_reference_t<_TQual<_TTypes>, _UQual<_UTypes>>...>; };
2335
2336 template<typename... _TTypes, typename... _UTypes>
2337 requires requires { typename tuple<common_type_t<_TTypes, _UTypes>...>; }
2338 struct common_type<tuple<_TTypes...>, tuple<_UTypes...>>
2339 { using type = tuple<common_type_t<_TTypes, _UTypes>...>; };
2340#endif // C++23
2341
2342 /// @}
2343
2344_GLIBCXX_END_NAMESPACE_VERSION
2345} // namespace std
2346
2347#endif // C++11
2348
2349#endif // _GLIBCXX_TUPLE