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