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