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