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