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