1// <tuple> -*- C++ -*- 2 3// Copyright (C) 2007-2020 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 <utility> 39#include <array> 40#include <bits/uses_allocator.h> 41#include <bits/invoke.h> 42#if __cplusplus > 201703L 43# include <compare> 44# define __cpp_lib_constexpr_tuple 201811L 45#endif 46 47namespace std _GLIBCXX_VISIBILITY(default) 48{ 49_GLIBCXX_BEGIN_NAMESPACE_VERSION 50 51 /** 52 * @addtogroup utilities 53 * @{ 54 */ 55 56 template<typename... _Elements> 57 class tuple; 58 59 template<typename _Tp> 60 struct __is_empty_non_tuple : is_empty<_Tp> { }; 61 62 // Using EBO for elements that are tuples causes ambiguous base errors. 63 template<typename _El0, typename... _El> 64 struct __is_empty_non_tuple<tuple<_El0, _El...>> : false_type { }; 65 66 // Use the Empty Base-class Optimization for empty, non-final types. 67 template<typename _Tp> 68 using __empty_not_final 69 = typename conditional<__is_final(_Tp), false_type, 70 __is_empty_non_tuple<_Tp>>::type; 71 72 template<std::size_t _Idx, typename _Head, 73 bool = __empty_not_final<_Head>::value> 74 struct _Head_base; 75 76 template<std::size_t _Idx, typename _Head> 77 struct _Head_base<_Idx, _Head, true> 78 : public _Head 79 { 80 constexpr _Head_base() 81 : _Head() { } 82 83 constexpr _Head_base(const _Head& __h) 84 : _Head(__h) { } 85 86 constexpr _Head_base(const _Head_base&) = default; 87 constexpr _Head_base(_Head_base&&) = default; 88 89 template<typename _UHead> 90 constexpr _Head_base(_UHead&& __h) 91 : _Head(std::forward<_UHead>(__h)) { } 92 93 _GLIBCXX20_CONSTEXPR 94 _Head_base(allocator_arg_t, __uses_alloc0) 95 : _Head() { } 96 97 template<typename _Alloc> 98 _GLIBCXX20_CONSTEXPR 99 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) 100 : _Head(allocator_arg, *__a._M_a) { } 101 102 template<typename _Alloc> 103 _GLIBCXX20_CONSTEXPR 104 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) 105 : _Head(*__a._M_a) { } 106 107 template<typename _UHead> 108 _GLIBCXX20_CONSTEXPR 109 _Head_base(__uses_alloc0, _UHead&& __uhead) 110 : _Head(std::forward<_UHead>(__uhead)) { } 111 112 template<typename _Alloc, typename _UHead> 113 _GLIBCXX20_CONSTEXPR 114 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) 115 : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { } 116 117 template<typename _Alloc, typename _UHead> 118 _GLIBCXX20_CONSTEXPR 119 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) 120 : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { } 121 122 static constexpr _Head& 123 _M_head(_Head_base& __b) noexcept { return __b; } 124 125 static constexpr const _Head& 126 _M_head(const _Head_base& __b) noexcept { return __b; } 127 }; 128 129 template<std::size_t _Idx, typename _Head> 130 struct _Head_base<_Idx, _Head, false> 131 { 132 constexpr _Head_base() 133 : _M_head_impl() { } 134 135 constexpr _Head_base(const _Head& __h) 136 : _M_head_impl(__h) { } 137 138 constexpr _Head_base(const _Head_base&) = default; 139 constexpr _Head_base(_Head_base&&) = default; 140 141 template<typename _UHead> 142 constexpr _Head_base(_UHead&& __h) 143 : _M_head_impl(std::forward<_UHead>(__h)) { } 144 145 _GLIBCXX20_CONSTEXPR 146 _Head_base(allocator_arg_t, __uses_alloc0) 147 : _M_head_impl() { } 148 149 template<typename _Alloc> 150 _GLIBCXX20_CONSTEXPR 151 _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) 152 : _M_head_impl(allocator_arg, *__a._M_a) { } 153 154 template<typename _Alloc> 155 _GLIBCXX20_CONSTEXPR 156 _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) 157 : _M_head_impl(*__a._M_a) { } 158 159 template<typename _UHead> 160 _GLIBCXX20_CONSTEXPR 161 _Head_base(__uses_alloc0, _UHead&& __uhead) 162 : _M_head_impl(std::forward<_UHead>(__uhead)) { } 163 164 template<typename _Alloc, typename _UHead> 165 _GLIBCXX20_CONSTEXPR 166 _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) 167 : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) 168 { } 169 170 template<typename _Alloc, typename _UHead> 171 _GLIBCXX20_CONSTEXPR 172 _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) 173 : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { } 174 175 static constexpr _Head& 176 _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; } 177 178 static constexpr const _Head& 179 _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; } 180 181 _Head _M_head_impl; 182 }; 183 184 /** 185 * Contains the actual implementation of the @c tuple template, stored 186 * as a recursive inheritance hierarchy from the first element (most 187 * derived class) to the last (least derived class). The @c Idx 188 * parameter gives the 0-based index of the element stored at this 189 * point in the hierarchy; we use it to implement a constant-time 190 * get() operation. 191 */ 192 template<std::size_t _Idx, typename... _Elements> 193 struct _Tuple_impl; 194 195 /** 196 * Recursive tuple implementation. Here we store the @c Head element 197 * and derive from a @c Tuple_impl containing the remaining elements 198 * (which contains the @c Tail). 199 */ 200 template<std::size_t _Idx, typename _Head, typename... _Tail> 201 struct _Tuple_impl<_Idx, _Head, _Tail...> 202 : public _Tuple_impl<_Idx + 1, _Tail...>, 203 private _Head_base<_Idx, _Head> 204 { 205 template<std::size_t, typename...> friend class _Tuple_impl; 206 207 typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited; 208 typedef _Head_base<_Idx, _Head> _Base; 209 210 static constexpr _Head& 211 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } 212 213 static constexpr const _Head& 214 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } 215 216 static constexpr _Inherited& 217 _M_tail(_Tuple_impl& __t) noexcept { return __t; } 218 219 static constexpr const _Inherited& 220 _M_tail(const _Tuple_impl& __t) noexcept { return __t; } 221 222 constexpr _Tuple_impl() 223 : _Inherited(), _Base() { } 224 225 explicit 226 constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail) 227 : _Inherited(__tail...), _Base(__head) { } 228 229 template<typename _UHead, typename... _UTail, typename = typename 230 enable_if<sizeof...(_Tail) == sizeof...(_UTail)>::type> 231 explicit 232 constexpr _Tuple_impl(_UHead&& __head, _UTail&&... __tail) 233 : _Inherited(std::forward<_UTail>(__tail)...), 234 _Base(std::forward<_UHead>(__head)) { } 235 236 constexpr _Tuple_impl(const _Tuple_impl&) = default; 237 238 // _GLIBCXX_RESOLVE_LIB_DEFECTS 239 // 2729. Missing SFINAE on std::pair::operator= 240 _Tuple_impl& operator=(const _Tuple_impl&) = delete; 241 242 constexpr 243 _Tuple_impl(_Tuple_impl&& __in) 244 noexcept(__and_<is_nothrow_move_constructible<_Head>, 245 is_nothrow_move_constructible<_Inherited>>::value) 246 : _Inherited(std::move(_M_tail(__in))), 247 _Base(std::forward<_Head>(_M_head(__in))) { } 248 249 template<typename... _UElements> 250 constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in) 251 : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), 252 _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { } 253 254 template<typename _UHead, typename... _UTails> 255 constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) 256 : _Inherited(std::move 257 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), 258 _Base(std::forward<_UHead> 259 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } 260 261 template<typename _Alloc> 262 _GLIBCXX20_CONSTEXPR 263 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) 264 : _Inherited(__tag, __a), 265 _Base(__tag, __use_alloc<_Head>(__a)) { } 266 267 template<typename _Alloc> 268 _GLIBCXX20_CONSTEXPR 269 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 270 const _Head& __head, const _Tail&... __tail) 271 : _Inherited(__tag, __a, __tail...), 272 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { } 273 274 template<typename _Alloc, typename _UHead, typename... _UTail, 275 typename = typename enable_if<sizeof...(_Tail) 276 == sizeof...(_UTail)>::type> 277 _GLIBCXX20_CONSTEXPR 278 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 279 _UHead&& __head, _UTail&&... __tail) 280 : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...), 281 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), 282 std::forward<_UHead>(__head)) { } 283 284 template<typename _Alloc> 285 _GLIBCXX20_CONSTEXPR 286 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 287 const _Tuple_impl& __in) 288 : _Inherited(__tag, __a, _M_tail(__in)), 289 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { } 290 291 template<typename _Alloc> 292 _GLIBCXX20_CONSTEXPR 293 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 294 _Tuple_impl&& __in) 295 : _Inherited(__tag, __a, std::move(_M_tail(__in))), 296 _Base(__use_alloc<_Head, _Alloc, _Head>(__a), 297 std::forward<_Head>(_M_head(__in))) { } 298 299 template<typename _Alloc, typename _UHead, typename... _UTails> 300 _GLIBCXX20_CONSTEXPR 301 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 302 const _Tuple_impl<_Idx, _UHead, _UTails...>& __in) 303 : _Inherited(__tag, __a, 304 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)), 305 _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a), 306 _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)) { } 307 308 template<typename _Alloc, typename _UHead, typename... _UTails> 309 _GLIBCXX20_CONSTEXPR 310 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 311 _Tuple_impl<_Idx, _UHead, _UTails...>&& __in) 312 : _Inherited(__tag, __a, std::move 313 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), 314 _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), 315 std::forward<_UHead> 316 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } 317 318 template<typename... _UElements> 319 _GLIBCXX20_CONSTEXPR 320 void 321 _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) 322 { 323 _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in); 324 _M_tail(*this)._M_assign( 325 _Tuple_impl<_Idx, _UElements...>::_M_tail(__in)); 326 } 327 328 template<typename _UHead, typename... _UTails> 329 _GLIBCXX20_CONSTEXPR 330 void 331 _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) 332 { 333 _M_head(*this) = std::forward<_UHead> 334 (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)); 335 _M_tail(*this)._M_assign( 336 std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))); 337 } 338 339 protected: 340 _GLIBCXX20_CONSTEXPR 341 void 342 _M_swap(_Tuple_impl& __in) 343 { 344 using std::swap; 345 swap(_M_head(*this), _M_head(__in)); 346 _Inherited::_M_swap(_M_tail(__in)); 347 } 348 }; 349 350 // Basis case of inheritance recursion. 351 template<std::size_t _Idx, typename _Head> 352 struct _Tuple_impl<_Idx, _Head> 353 : private _Head_base<_Idx, _Head> 354 { 355 template<std::size_t, typename...> friend class _Tuple_impl; 356 357 typedef _Head_base<_Idx, _Head> _Base; 358 359 static constexpr _Head& 360 _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } 361 362 static constexpr const _Head& 363 _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } 364 365 constexpr _Tuple_impl() 366 : _Base() { } 367 368 explicit 369 constexpr _Tuple_impl(const _Head& __head) 370 : _Base(__head) { } 371 372 template<typename _UHead> 373 explicit 374 constexpr _Tuple_impl(_UHead&& __head) 375 : _Base(std::forward<_UHead>(__head)) { } 376 377 constexpr _Tuple_impl(const _Tuple_impl&) = default; 378 379 // _GLIBCXX_RESOLVE_LIB_DEFECTS 380 // 2729. Missing SFINAE on std::pair::operator= 381 _Tuple_impl& operator=(const _Tuple_impl&) = delete; 382 383 constexpr 384 _Tuple_impl(_Tuple_impl&& __in) 385 noexcept(is_nothrow_move_constructible<_Head>::value) 386 : _Base(std::forward<_Head>(_M_head(__in))) { } 387 388 template<typename _UHead> 389 constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in) 390 : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in)) { } 391 392 template<typename _UHead> 393 constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in) 394 : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) 395 { } 396 397 template<typename _Alloc> 398 _GLIBCXX20_CONSTEXPR 399 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) 400 : _Base(__tag, __use_alloc<_Head>(__a)) { } 401 402 template<typename _Alloc> 403 _GLIBCXX20_CONSTEXPR 404 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 405 const _Head& __head) 406 : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { } 407 408 template<typename _Alloc, typename _UHead> 409 _GLIBCXX20_CONSTEXPR 410 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 411 _UHead&& __head) 412 : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), 413 std::forward<_UHead>(__head)) { } 414 415 template<typename _Alloc> 416 _GLIBCXX20_CONSTEXPR 417 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 418 const _Tuple_impl& __in) 419 : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { } 420 421 template<typename _Alloc> 422 _GLIBCXX20_CONSTEXPR 423 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 424 _Tuple_impl&& __in) 425 : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), 426 std::forward<_Head>(_M_head(__in))) { } 427 428 template<typename _Alloc, typename _UHead> 429 _GLIBCXX20_CONSTEXPR 430 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 431 const _Tuple_impl<_Idx, _UHead>& __in) 432 : _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a), 433 _Tuple_impl<_Idx, _UHead>::_M_head(__in)) { } 434 435 template<typename _Alloc, typename _UHead> 436 _GLIBCXX20_CONSTEXPR 437 _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, 438 _Tuple_impl<_Idx, _UHead>&& __in) 439 : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), 440 std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) 441 { } 442 443 template<typename _UHead> 444 _GLIBCXX20_CONSTEXPR 445 void 446 _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) 447 { 448 _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in); 449 } 450 451 template<typename _UHead> 452 _GLIBCXX20_CONSTEXPR 453 void 454 _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) 455 { 456 _M_head(*this) 457 = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)); 458 } 459 460 protected: 461 _GLIBCXX20_CONSTEXPR 462 void 463 _M_swap(_Tuple_impl& __in) 464 { 465 using std::swap; 466 swap(_M_head(*this), _M_head(__in)); 467 } 468 }; 469 470 // Concept utility functions, reused in conditionally-explicit 471 // constructors. 472 template<bool, typename... _Types> 473 struct _TupleConstraints 474 { 475 template<typename _Tp, typename _Up> // Workaround for PR 96592 476 using is_constructible 477 = __bool_constant<__is_constructible(_Tp, _Up)>; 478 479 // Constraint for a non-explicit constructor. 480 // True iff each Ti in _Types... can be constructed from Ui in _UTypes... 481 // and every Ui is implicitly convertible to Ti. 482 template<typename... _UTypes> 483 static constexpr bool __is_implicitly_constructible() 484 { 485 return __and_<is_constructible<_Types, _UTypes>..., 486 is_convertible<_UTypes, _Types>... 487 >::value; 488 } 489 490 // Constraint for a non-explicit constructor. 491 // True iff each Ti in _Types... can be constructed from Ui in _UTypes... 492 // but not every Ui is implicitly convertible to Ti. 493 template<typename... _UTypes> 494 static constexpr bool __is_explicitly_constructible() 495 { 496 return __and_<is_constructible<_Types, _UTypes>..., 497 __not_<__and_<is_convertible<_UTypes, _Types>...>> 498 >::value; 499 } 500 501 static constexpr bool __is_implicitly_default_constructible() 502 { 503 return __and_<std::__is_implicitly_default_constructible<_Types>... 504 >::value; 505 } 506 507 static constexpr bool __is_explicitly_default_constructible() 508 { 509 return __and_<is_default_constructible<_Types>..., 510 __not_<__and_< 511 std::__is_implicitly_default_constructible<_Types>...> 512 >>::value; 513 } 514 }; 515 516 // Partial specialization used when a required precondition isn't met, 517 // e.g. when sizeof...(_Types) != sizeof...(_UTypes). 518 template<typename... _Types> 519 struct _TupleConstraints<false, _Types...> 520 { 521 template<typename... _UTypes> 522 static constexpr bool __is_implicitly_constructible() 523 { return false; } 524 525 template<typename... _UTypes> 526 static constexpr bool __is_explicitly_constructible() 527 { return false; } 528 }; 529 530 /// Primary class template, tuple 531 template<typename... _Elements> 532 class tuple : public _Tuple_impl<0, _Elements...> 533 { 534 typedef _Tuple_impl<0, _Elements...> _Inherited; 535 536 template<bool _Cond> 537 using _TCC = _TupleConstraints<_Cond, _Elements...>; 538 539 // Constraint for non-explicit default constructor 540 template<bool _Dummy> 541 using _ImplicitDefaultCtor = __enable_if_t< 542 _TCC<_Dummy>::__is_implicitly_default_constructible(), 543 bool>; 544 545 // Constraint for explicit default constructor 546 template<bool _Dummy> 547 using _ExplicitDefaultCtor = __enable_if_t< 548 _TCC<_Dummy>::__is_explicitly_default_constructible(), 549 bool>; 550 551 // Constraint for non-explicit constructors 552 template<bool _Cond, typename... _Args> 553 using _ImplicitCtor = __enable_if_t< 554 _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(), 555 bool>; 556 557 // Constraint for non-explicit constructors 558 template<bool _Cond, typename... _Args> 559 using _ExplicitCtor = __enable_if_t< 560 _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(), 561 bool>; 562 563 template<typename... _UElements> 564 static constexpr 565 __enable_if_t<sizeof...(_UElements) == sizeof...(_Elements), bool> 566 __assignable() 567 { return __and_<is_assignable<_Elements&, _UElements>...>::value; } 568 569 // Condition for noexcept-specifier of an assignment operator. 570 template<typename... _UElements> 571 static constexpr bool __nothrow_assignable() 572 { 573 return 574 __and_<is_nothrow_assignable<_Elements&, _UElements>...>::value; 575 } 576 577 // Condition for noexcept-specifier of a constructor. 578 template<typename... _UElements> 579 static constexpr bool __nothrow_constructible() 580 { 581 return 582 __and_<is_nothrow_constructible<_Elements, _UElements>...>::value; 583 } 584 585 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1. 586 template<typename _Up> 587 static constexpr bool __valid_args() 588 { 589 return sizeof...(_Elements) == 1 590 && !is_same<tuple, __remove_cvref_t<_Up>>::value; 591 } 592 593 // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1. 594 template<typename, typename, typename... _Tail> 595 static constexpr bool __valid_args() 596 { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); } 597 598 /* Constraint for constructors with a tuple<UTypes...> parameter ensures 599 * that the constructor is only viable when it would not interfere with 600 * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&). 601 * Such constructors are only viable if: 602 * either sizeof...(Types) != 1, 603 * or (when Types... expands to T and UTypes... expands to U) 604 * is_convertible_v<TUPLE, T>, is_constructible_v<T, TUPLE>, 605 * and is_same_v<T, U> are all false. 606 */ 607 template<typename _Tuple, typename = tuple, 608 typename = __remove_cvref_t<_Tuple>> 609 struct _UseOtherCtor 610 : false_type 611 { }; 612 // If TUPLE is convertible to the single element in *this, 613 // then TUPLE should match tuple(UTypes&&...) instead. 614 template<typename _Tuple, typename _Tp, typename _Up> 615 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>> 616 : __or_<is_convertible<_Tuple, _Tp>, is_constructible<_Tp, _Tuple>> 617 { }; 618 // If TUPLE and *this each have a single element of the same type, 619 // then TUPLE should match a copy/move constructor instead. 620 template<typename _Tuple, typename _Tp> 621 struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>> 622 : true_type 623 { }; 624 625 // Return true iff sizeof...(Types) == 1 && tuple_size_v<TUPLE> == 1 626 // and the single element in Types can be initialized from TUPLE, 627 // or is the same type as tuple_element_t<0, TUPLE>. 628 template<typename _Tuple> 629 static constexpr bool __use_other_ctor() 630 { return _UseOtherCtor<_Tuple>::value; } 631 632 public: 633 template<typename _Dummy = void, 634 _ImplicitDefaultCtor<is_void<_Dummy>::value> = true> 635 constexpr 636 tuple() 637 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value) 638 : _Inherited() { } 639 640 template<typename _Dummy = void, 641 _ExplicitDefaultCtor<is_void<_Dummy>::value> = false> 642 explicit constexpr 643 tuple() 644 noexcept(__and_<is_nothrow_default_constructible<_Elements>...>::value) 645 : _Inherited() { } 646 647 template<bool _NotEmpty = (sizeof...(_Elements) >= 1), 648 _ImplicitCtor<_NotEmpty, const _Elements&...> = true> 649 constexpr 650 tuple(const _Elements&... __elements) 651 noexcept(__nothrow_constructible<const _Elements&...>()) 652 : _Inherited(__elements...) { } 653 654 template<bool _NotEmpty = (sizeof...(_Elements) >= 1), 655 _ExplicitCtor<_NotEmpty, const _Elements&...> = false> 656 explicit constexpr 657 tuple(const _Elements&... __elements) 658 noexcept(__nothrow_constructible<const _Elements&...>()) 659 : _Inherited(__elements...) { } 660 661 template<typename... _UElements, 662 bool _Valid = __valid_args<_UElements...>(), 663 _ImplicitCtor<_Valid, _UElements...> = true> 664 constexpr 665 tuple(_UElements&&... __elements) 666 noexcept(__nothrow_constructible<_UElements...>()) 667 : _Inherited(std::forward<_UElements>(__elements)...) { } 668 669 template<typename... _UElements, 670 bool _Valid = __valid_args<_UElements...>(), 671 _ExplicitCtor<_Valid, _UElements...> = false> 672 explicit constexpr 673 tuple(_UElements&&... __elements) 674 noexcept(__nothrow_constructible<_UElements...>()) 675 : _Inherited(std::forward<_UElements>(__elements)...) { } 676 677 constexpr tuple(const tuple&) = default; 678 679 constexpr tuple(tuple&&) = default; 680 681 template<typename... _UElements, 682 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) 683 && !__use_other_ctor<const tuple<_UElements...>&>(), 684 _ImplicitCtor<_Valid, const _UElements&...> = true> 685 constexpr 686 tuple(const tuple<_UElements...>& __in) 687 noexcept(__nothrow_constructible<const _UElements&...>()) 688 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) 689 { } 690 691 template<typename... _UElements, 692 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) 693 && !__use_other_ctor<const tuple<_UElements...>&>(), 694 _ExplicitCtor<_Valid, const _UElements&...> = false> 695 explicit constexpr 696 tuple(const tuple<_UElements...>& __in) 697 noexcept(__nothrow_constructible<const _UElements&...>()) 698 : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) 699 { } 700 701 template<typename... _UElements, 702 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) 703 && !__use_other_ctor<tuple<_UElements...>&&>(), 704 _ImplicitCtor<_Valid, _UElements...> = true> 705 constexpr 706 tuple(tuple<_UElements...>&& __in) 707 noexcept(__nothrow_constructible<_UElements...>()) 708 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } 709 710 template<typename... _UElements, 711 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) 712 && !__use_other_ctor<tuple<_UElements...>&&>(), 713 _ExplicitCtor<_Valid, _UElements...> = false> 714 explicit constexpr 715 tuple(tuple<_UElements...>&& __in) 716 noexcept(__nothrow_constructible<_UElements...>()) 717 : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } 718 719 // Allocator-extended constructors. 720 721 template<typename _Alloc, 722 _ImplicitDefaultCtor<is_object<_Alloc>::value> = true> 723 _GLIBCXX20_CONSTEXPR 724 tuple(allocator_arg_t __tag, const _Alloc& __a) 725 : _Inherited(__tag, __a) { } 726 727 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1), 728 _ImplicitCtor<_NotEmpty, const _Elements&...> = true> 729 _GLIBCXX20_CONSTEXPR 730 tuple(allocator_arg_t __tag, const _Alloc& __a, 731 const _Elements&... __elements) 732 : _Inherited(__tag, __a, __elements...) { } 733 734 template<typename _Alloc, bool _NotEmpty = (sizeof...(_Elements) >= 1), 735 _ExplicitCtor<_NotEmpty, const _Elements&...> = false> 736 _GLIBCXX20_CONSTEXPR 737 explicit 738 tuple(allocator_arg_t __tag, const _Alloc& __a, 739 const _Elements&... __elements) 740 : _Inherited(__tag, __a, __elements...) { } 741 742 template<typename _Alloc, typename... _UElements, 743 bool _Valid = __valid_args<_UElements...>(), 744 _ImplicitCtor<_Valid, _UElements...> = true> 745 _GLIBCXX20_CONSTEXPR 746 tuple(allocator_arg_t __tag, const _Alloc& __a, 747 _UElements&&... __elements) 748 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) 749 { } 750 751 template<typename _Alloc, typename... _UElements, 752 bool _Valid = __valid_args<_UElements...>(), 753 _ExplicitCtor<_Valid, _UElements...> = false> 754 _GLIBCXX20_CONSTEXPR 755 explicit 756 tuple(allocator_arg_t __tag, const _Alloc& __a, 757 _UElements&&... __elements) 758 : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) 759 { } 760 761 template<typename _Alloc> 762 _GLIBCXX20_CONSTEXPR 763 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) 764 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { } 765 766 template<typename _Alloc> 767 _GLIBCXX20_CONSTEXPR 768 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) 769 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } 770 771 template<typename _Alloc, typename... _UElements, 772 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) 773 && !__use_other_ctor<const tuple<_UElements...>&>(), 774 _ImplicitCtor<_Valid, const _UElements&...> = true> 775 _GLIBCXX20_CONSTEXPR 776 tuple(allocator_arg_t __tag, const _Alloc& __a, 777 const tuple<_UElements...>& __in) 778 : _Inherited(__tag, __a, 779 static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) 780 { } 781 782 template<typename _Alloc, typename... _UElements, 783 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) 784 && !__use_other_ctor<const tuple<_UElements...>&>(), 785 _ExplicitCtor<_Valid, const _UElements&...> = false> 786 _GLIBCXX20_CONSTEXPR 787 explicit 788 tuple(allocator_arg_t __tag, const _Alloc& __a, 789 const tuple<_UElements...>& __in) 790 : _Inherited(__tag, __a, 791 static_cast<const _Tuple_impl<0, _UElements...>&>(__in)) 792 { } 793 794 template<typename _Alloc, typename... _UElements, 795 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) 796 && !__use_other_ctor<tuple<_UElements...>&&>(), 797 _ImplicitCtor<_Valid, _UElements...> = true> 798 _GLIBCXX20_CONSTEXPR 799 tuple(allocator_arg_t __tag, const _Alloc& __a, 800 tuple<_UElements...>&& __in) 801 : _Inherited(__tag, __a, 802 static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) 803 { } 804 805 template<typename _Alloc, typename... _UElements, 806 bool _Valid = (sizeof...(_Elements) == sizeof...(_UElements)) 807 && !__use_other_ctor<tuple<_UElements...>&&>(), 808 _ExplicitCtor<_Valid, _UElements...> = false> 809 _GLIBCXX20_CONSTEXPR 810 explicit 811 tuple(allocator_arg_t __tag, const _Alloc& __a, 812 tuple<_UElements...>&& __in) 813 : _Inherited(__tag, __a, 814 static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) 815 { } 816 817 // tuple assignment 818 819 _GLIBCXX20_CONSTEXPR 820 tuple& 821 operator=(typename conditional<__assignable<const _Elements&...>(), 822 const tuple&, 823 const __nonesuch&>::type __in) 824 noexcept(__nothrow_assignable<const _Elements&...>()) 825 { 826 this->_M_assign(__in); 827 return *this; 828 } 829 830 _GLIBCXX20_CONSTEXPR 831 tuple& 832 operator=(typename conditional<__assignable<_Elements...>(), 833 tuple&&, 834 __nonesuch&&>::type __in) 835 noexcept(__nothrow_assignable<_Elements...>()) 836 { 837 this->_M_assign(std::move(__in)); 838 return *this; 839 } 840 841 template<typename... _UElements> 842 _GLIBCXX20_CONSTEXPR 843 __enable_if_t<__assignable<const _UElements&...>(), tuple&> 844 operator=(const tuple<_UElements...>& __in) 845 noexcept(__nothrow_assignable<const _UElements&...>()) 846 { 847 this->_M_assign(__in); 848 return *this; 849 } 850 851 template<typename... _UElements> 852 _GLIBCXX20_CONSTEXPR 853 __enable_if_t<__assignable<_UElements...>(), tuple&> 854 operator=(tuple<_UElements...>&& __in) 855 noexcept(__nothrow_assignable<_UElements...>()) 856 { 857 this->_M_assign(std::move(__in)); 858 return *this; 859 } 860 861 // tuple swap 862 _GLIBCXX20_CONSTEXPR 863 void 864 swap(tuple& __in) 865 noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value) 866 { _Inherited::_M_swap(__in); } 867 }; 868 869#if __cpp_deduction_guides >= 201606 870 template<typename... _UTypes> 871 tuple(_UTypes...) -> tuple<_UTypes...>; 872 template<typename _T1, typename _T2> 873 tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>; 874 template<typename _Alloc, typename... _UTypes> 875 tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>; 876 template<typename _Alloc, typename _T1, typename _T2> 877 tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>; 878 template<typename _Alloc, typename... _UTypes> 879 tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>; 880#endif 881 882 // Explicit specialization, zero-element tuple. 883 template<> 884 class tuple<> 885 { 886 public: 887 _GLIBCXX20_CONSTEXPR 888 void swap(tuple&) noexcept { /* no-op */ } 889 // We need the default since we're going to define no-op 890 // allocator constructors. 891 tuple() = default; 892 // No-op allocator constructors. 893 template<typename _Alloc> 894 _GLIBCXX20_CONSTEXPR 895 tuple(allocator_arg_t, const _Alloc&) noexcept { } 896 template<typename _Alloc> 897 _GLIBCXX20_CONSTEXPR 898 tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { } 899 }; 900 901 /// Partial specialization, 2-element tuple. 902 /// Includes construction and assignment from a pair. 903 template<typename _T1, typename _T2> 904 class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2> 905 { 906 typedef _Tuple_impl<0, _T1, _T2> _Inherited; 907 908 // Constraint for non-explicit default constructor 909 template<bool _Dummy, typename _U1, typename _U2> 910 using _ImplicitDefaultCtor = __enable_if_t< 911 _TupleConstraints<_Dummy, _U1, _U2>:: 912 __is_implicitly_default_constructible(), 913 bool>; 914 915 // Constraint for explicit default constructor 916 template<bool _Dummy, typename _U1, typename _U2> 917 using _ExplicitDefaultCtor = __enable_if_t< 918 _TupleConstraints<_Dummy, _U1, _U2>:: 919 __is_explicitly_default_constructible(), 920 bool>; 921 922 template<bool _Dummy> 923 using _TCC = _TupleConstraints<_Dummy, _T1, _T2>; 924 925 // Constraint for non-explicit constructors 926 template<bool _Cond, typename _U1, typename _U2> 927 using _ImplicitCtor = __enable_if_t< 928 _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(), 929 bool>; 930 931 // Constraint for non-explicit constructors 932 template<bool _Cond, typename _U1, typename _U2> 933 using _ExplicitCtor = __enable_if_t< 934 _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(), 935 bool>; 936 937 template<typename _U1, typename _U2> 938 static constexpr bool __assignable() 939 { 940 return __and_<is_assignable<_T1&, _U1>, 941 is_assignable<_T2&, _U2>>::value; 942 } 943 944 template<typename _U1, typename _U2> 945 static constexpr bool __nothrow_assignable() 946 { 947 return __and_<is_nothrow_assignable<_T1&, _U1>, 948 is_nothrow_assignable<_T2&, _U2>>::value; 949 } 950 951 template<typename _U1, typename _U2> 952 static constexpr bool __nothrow_constructible() 953 { 954 return __and_<is_nothrow_constructible<_T1, _U1>, 955 is_nothrow_constructible<_T2, _U2>>::value; 956 } 957 958 static constexpr bool __nothrow_default_constructible() 959 { 960 return __and_<is_nothrow_default_constructible<_T1>, 961 is_nothrow_default_constructible<_T2>>::value; 962 } 963 964 template<typename _U1> 965 static constexpr bool __is_alloc_arg() 966 { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; } 967 968 public: 969 template<bool _Dummy = true, 970 _ImplicitDefaultCtor<_Dummy, _T1, _T2> = true> 971 constexpr 972 tuple() 973 noexcept(__nothrow_default_constructible()) 974 : _Inherited() { } 975 976 template<bool _Dummy = true, 977 _ExplicitDefaultCtor<_Dummy, _T1, _T2> = false> 978 explicit constexpr 979 tuple() 980 noexcept(__nothrow_default_constructible()) 981 : _Inherited() { } 982 983 template<bool _Dummy = true, 984 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true> 985 constexpr 986 tuple(const _T1& __a1, const _T2& __a2) 987 noexcept(__nothrow_constructible<const _T1&, const _T2&>()) 988 : _Inherited(__a1, __a2) { } 989 990 template<bool _Dummy = true, 991 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false> 992 explicit constexpr 993 tuple(const _T1& __a1, const _T2& __a2) 994 noexcept(__nothrow_constructible<const _T1&, const _T2&>()) 995 : _Inherited(__a1, __a2) { } 996 997 template<typename _U1, typename _U2, 998 _ImplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = true> 999 constexpr 1000 tuple(_U1&& __a1, _U2&& __a2) 1001 noexcept(__nothrow_constructible<_U1, _U2>()) 1002 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } 1003 1004 template<typename _U1, typename _U2, 1005 _ExplicitCtor<!__is_alloc_arg<_U1>(), _U1, _U2> = false> 1006 explicit constexpr 1007 tuple(_U1&& __a1, _U2&& __a2) 1008 noexcept(__nothrow_constructible<_U1, _U2>()) 1009 : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } 1010 1011 constexpr tuple(const tuple&) = default; 1012 1013 constexpr tuple(tuple&&) = default; 1014 1015 template<typename _U1, typename _U2, 1016 _ImplicitCtor<true, const _U1&, const _U2&> = true> 1017 constexpr 1018 tuple(const tuple<_U1, _U2>& __in) 1019 noexcept(__nothrow_constructible<const _U1&, const _U2&>()) 1020 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { } 1021 1022 template<typename _U1, typename _U2, 1023 _ExplicitCtor<true, const _U1&, const _U2&> = false> 1024 explicit constexpr 1025 tuple(const tuple<_U1, _U2>& __in) 1026 noexcept(__nothrow_constructible<const _U1&, const _U2&>()) 1027 : _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { } 1028 1029 template<typename _U1, typename _U2, 1030 _ImplicitCtor<true, _U1, _U2> = true> 1031 constexpr 1032 tuple(tuple<_U1, _U2>&& __in) 1033 noexcept(__nothrow_constructible<_U1, _U2>()) 1034 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } 1035 1036 template<typename _U1, typename _U2, 1037 _ExplicitCtor<true, _U1, _U2> = false> 1038 explicit constexpr 1039 tuple(tuple<_U1, _U2>&& __in) 1040 noexcept(__nothrow_constructible<_U1, _U2>()) 1041 : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } 1042 1043 template<typename _U1, typename _U2, 1044 _ImplicitCtor<true, const _U1&, const _U2&> = true> 1045 constexpr 1046 tuple(const pair<_U1, _U2>& __in) 1047 noexcept(__nothrow_constructible<const _U1&, const _U2&>()) 1048 : _Inherited(__in.first, __in.second) { } 1049 1050 template<typename _U1, typename _U2, 1051 _ExplicitCtor<true, const _U1&, const _U2&> = false> 1052 explicit constexpr 1053 tuple(const pair<_U1, _U2>& __in) 1054 noexcept(__nothrow_constructible<const _U1&, const _U2&>()) 1055 : _Inherited(__in.first, __in.second) { } 1056 1057 template<typename _U1, typename _U2, 1058 _ImplicitCtor<true, _U1, _U2> = true> 1059 constexpr 1060 tuple(pair<_U1, _U2>&& __in) 1061 noexcept(__nothrow_constructible<_U1, _U2>()) 1062 : _Inherited(std::forward<_U1>(__in.first), 1063 std::forward<_U2>(__in.second)) { } 1064 1065 template<typename _U1, typename _U2, 1066 _ExplicitCtor<true, _U1, _U2> = false> 1067 explicit constexpr 1068 tuple(pair<_U1, _U2>&& __in) 1069 noexcept(__nothrow_constructible<_U1, _U2>()) 1070 : _Inherited(std::forward<_U1>(__in.first), 1071 std::forward<_U2>(__in.second)) { } 1072 1073 // Allocator-extended constructors. 1074 1075 template<typename _Alloc, 1076 _ImplicitDefaultCtor<is_object<_Alloc>::value, _T1, _T2> = true> 1077 _GLIBCXX20_CONSTEXPR 1078 tuple(allocator_arg_t __tag, const _Alloc& __a) 1079 : _Inherited(__tag, __a) { } 1080 1081 template<typename _Alloc, bool _Dummy = true, 1082 _ImplicitCtor<_Dummy, const _T1&, const _T2&> = true> 1083 _GLIBCXX20_CONSTEXPR 1084 tuple(allocator_arg_t __tag, const _Alloc& __a, 1085 const _T1& __a1, const _T2& __a2) 1086 : _Inherited(__tag, __a, __a1, __a2) { } 1087 1088 template<typename _Alloc, bool _Dummy = true, 1089 _ExplicitCtor<_Dummy, const _T1&, const _T2&> = false> 1090 explicit 1091 _GLIBCXX20_CONSTEXPR 1092 tuple(allocator_arg_t __tag, const _Alloc& __a, 1093 const _T1& __a1, const _T2& __a2) 1094 : _Inherited(__tag, __a, __a1, __a2) { } 1095 1096 template<typename _Alloc, typename _U1, typename _U2, 1097 _ImplicitCtor<true, _U1, _U2> = true> 1098 _GLIBCXX20_CONSTEXPR 1099 tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2) 1100 : _Inherited(__tag, __a, std::forward<_U1>(__a1), 1101 std::forward<_U2>(__a2)) { } 1102 1103 template<typename _Alloc, typename _U1, typename _U2, 1104 _ExplicitCtor<true, _U1, _U2> = false> 1105 explicit 1106 _GLIBCXX20_CONSTEXPR 1107 tuple(allocator_arg_t __tag, const _Alloc& __a, 1108 _U1&& __a1, _U2&& __a2) 1109 : _Inherited(__tag, __a, std::forward<_U1>(__a1), 1110 std::forward<_U2>(__a2)) { } 1111 1112 template<typename _Alloc> 1113 _GLIBCXX20_CONSTEXPR 1114 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) 1115 : _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { } 1116 1117 template<typename _Alloc> 1118 _GLIBCXX20_CONSTEXPR 1119 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) 1120 : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } 1121 1122 template<typename _Alloc, typename _U1, typename _U2, 1123 _ImplicitCtor<true, const _U1&, const _U2&> = true> 1124 _GLIBCXX20_CONSTEXPR 1125 tuple(allocator_arg_t __tag, const _Alloc& __a, 1126 const tuple<_U1, _U2>& __in) 1127 : _Inherited(__tag, __a, 1128 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) 1129 { } 1130 1131 template<typename _Alloc, typename _U1, typename _U2, 1132 _ExplicitCtor<true, const _U1&, const _U2&> = false> 1133 explicit 1134 _GLIBCXX20_CONSTEXPR 1135 tuple(allocator_arg_t __tag, const _Alloc& __a, 1136 const tuple<_U1, _U2>& __in) 1137 : _Inherited(__tag, __a, 1138 static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) 1139 { } 1140 1141 template<typename _Alloc, typename _U1, typename _U2, 1142 _ImplicitCtor<true, _U1, _U2> = true> 1143 _GLIBCXX20_CONSTEXPR 1144 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in) 1145 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) 1146 { } 1147 1148 template<typename _Alloc, typename _U1, typename _U2, 1149 _ExplicitCtor<true, _U1, _U2> = false> 1150 explicit 1151 _GLIBCXX20_CONSTEXPR 1152 tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in) 1153 : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) 1154 { } 1155 1156 template<typename _Alloc, typename _U1, typename _U2, 1157 _ImplicitCtor<true, const _U1&, const _U2&> = true> 1158 _GLIBCXX20_CONSTEXPR 1159 tuple(allocator_arg_t __tag, const _Alloc& __a, 1160 const pair<_U1, _U2>& __in) 1161 : _Inherited(__tag, __a, __in.first, __in.second) { } 1162 1163 template<typename _Alloc, typename _U1, typename _U2, 1164 _ExplicitCtor<true, const _U1&, const _U2&> = false> 1165 explicit 1166 _GLIBCXX20_CONSTEXPR 1167 tuple(allocator_arg_t __tag, const _Alloc& __a, 1168 const pair<_U1, _U2>& __in) 1169 : _Inherited(__tag, __a, __in.first, __in.second) { } 1170 1171 template<typename _Alloc, typename _U1, typename _U2, 1172 _ImplicitCtor<true, _U1, _U2> = true> 1173 _GLIBCXX20_CONSTEXPR 1174 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in) 1175 : _Inherited(__tag, __a, std::forward<_U1>(__in.first), 1176 std::forward<_U2>(__in.second)) { } 1177 1178 template<typename _Alloc, typename _U1, typename _U2, 1179 _ExplicitCtor<true, _U1, _U2> = false> 1180 explicit 1181 _GLIBCXX20_CONSTEXPR 1182 tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in) 1183 : _Inherited(__tag, __a, std::forward<_U1>(__in.first), 1184 std::forward<_U2>(__in.second)) { } 1185 1186 // Tuple assignment. 1187 1188 _GLIBCXX20_CONSTEXPR 1189 tuple& 1190 operator=(typename conditional<__assignable<const _T1&, const _T2&>(), 1191 const tuple&, 1192 const __nonesuch&>::type __in) 1193 noexcept(__nothrow_assignable<const _T1&, const _T2&>()) 1194 { 1195 this->_M_assign(__in); 1196 return *this; 1197 } 1198 1199 _GLIBCXX20_CONSTEXPR 1200 tuple& 1201 operator=(typename conditional<__assignable<_T1, _T2>(), 1202 tuple&&, 1203 __nonesuch&&>::type __in) 1204 noexcept(__nothrow_assignable<_T1, _T2>()) 1205 { 1206 this->_M_assign(std::move(__in)); 1207 return *this; 1208 } 1209 1210 template<typename _U1, typename _U2> 1211 _GLIBCXX20_CONSTEXPR 1212 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&> 1213 operator=(const tuple<_U1, _U2>& __in) 1214 noexcept(__nothrow_assignable<const _U1&, const _U2&>()) 1215 { 1216 this->_M_assign(__in); 1217 return *this; 1218 } 1219 1220 template<typename _U1, typename _U2> 1221 _GLIBCXX20_CONSTEXPR 1222 __enable_if_t<__assignable<_U1, _U2>(), tuple&> 1223 operator=(tuple<_U1, _U2>&& __in) 1224 noexcept(__nothrow_assignable<_U1, _U2>()) 1225 { 1226 this->_M_assign(std::move(__in)); 1227 return *this; 1228 } 1229 1230 template<typename _U1, typename _U2> 1231 _GLIBCXX20_CONSTEXPR 1232 __enable_if_t<__assignable<const _U1&, const _U2&>(), tuple&> 1233 operator=(const pair<_U1, _U2>& __in) 1234 noexcept(__nothrow_assignable<const _U1&, const _U2&>()) 1235 { 1236 this->_M_head(*this) = __in.first; 1237 this->_M_tail(*this)._M_head(*this) = __in.second; 1238 return *this; 1239 } 1240 1241 template<typename _U1, typename _U2> 1242 _GLIBCXX20_CONSTEXPR 1243 __enable_if_t<__assignable<_U1, _U2>(), tuple&> 1244 operator=(pair<_U1, _U2>&& __in) 1245 noexcept(__nothrow_assignable<_U1, _U2>()) 1246 { 1247 this->_M_head(*this) = std::forward<_U1>(__in.first); 1248 this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second); 1249 return *this; 1250 } 1251 1252 _GLIBCXX20_CONSTEXPR 1253 void 1254 swap(tuple& __in) 1255 noexcept(__and_<__is_nothrow_swappable<_T1>, 1256 __is_nothrow_swappable<_T2>>::value) 1257 { _Inherited::_M_swap(__in); } 1258 }; 1259 1260 1261 /// class tuple_size 1262 template<typename... _Elements> 1263 struct tuple_size<tuple<_Elements...>> 1264 : public integral_constant<std::size_t, sizeof...(_Elements)> { }; 1265 1266#if __cplusplus > 201402L 1267 template <typename _Tp> 1268 inline constexpr size_t tuple_size_v = tuple_size<_Tp>::value; 1269#endif 1270 1271 /** 1272 * Recursive case for tuple_element: strip off the first element in 1273 * the tuple and retrieve the (i-1)th element of the remaining tuple. 1274 */ 1275 template<std::size_t __i, typename _Head, typename... _Tail> 1276 struct tuple_element<__i, tuple<_Head, _Tail...> > 1277 : tuple_element<__i - 1, tuple<_Tail...> > { }; 1278 1279 /** 1280 * Basis case for tuple_element: The first element is the one we're seeking. 1281 */ 1282 template<typename _Head, typename... _Tail> 1283 struct tuple_element<0, tuple<_Head, _Tail...> > 1284 { 1285 typedef _Head type; 1286 }; 1287 1288 /** 1289 * Error case for tuple_element: invalid index. 1290 */ 1291 template<size_t __i> 1292 struct tuple_element<__i, tuple<>> 1293 { 1294 static_assert(__i < tuple_size<tuple<>>::value, 1295 "tuple index is in range"); 1296 }; 1297 1298 template<std::size_t __i, typename _Head, typename... _Tail> 1299 constexpr _Head& 1300 __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 1301 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } 1302 1303 template<std::size_t __i, typename _Head, typename... _Tail> 1304 constexpr const _Head& 1305 __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 1306 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } 1307 1308 /// Return a reference to the ith element of a tuple. 1309 template<std::size_t __i, typename... _Elements> 1310 constexpr __tuple_element_t<__i, tuple<_Elements...>>& 1311 get(tuple<_Elements...>& __t) noexcept 1312 { return std::__get_helper<__i>(__t); } 1313 1314 /// Return a const reference to the ith element of a const tuple. 1315 template<std::size_t __i, typename... _Elements> 1316 constexpr const __tuple_element_t<__i, tuple<_Elements...>>& 1317 get(const tuple<_Elements...>& __t) noexcept 1318 { return std::__get_helper<__i>(__t); } 1319 1320 /// Return an rvalue reference to the ith element of a tuple rvalue. 1321 template<std::size_t __i, typename... _Elements> 1322 constexpr __tuple_element_t<__i, tuple<_Elements...>>&& 1323 get(tuple<_Elements...>&& __t) noexcept 1324 { 1325 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; 1326 return std::forward<__element_type&&>(std::get<__i>(__t)); 1327 } 1328 1329 /// Return a const rvalue reference to the ith element of a const tuple rvalue. 1330 template<std::size_t __i, typename... _Elements> 1331 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&& 1332 get(const tuple<_Elements...>&& __t) noexcept 1333 { 1334 typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; 1335 return std::forward<const __element_type&&>(std::get<__i>(__t)); 1336 } 1337 1338#if __cplusplus >= 201402L 1339 1340#define __cpp_lib_tuples_by_type 201304 1341 1342 template<typename _Head, size_t __i, typename... _Tail> 1343 constexpr _Head& 1344 __get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 1345 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } 1346 1347 template<typename _Head, size_t __i, typename... _Tail> 1348 constexpr const _Head& 1349 __get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 1350 { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } 1351 1352 /// Return a reference to the unique element of type _Tp of a tuple. 1353 template <typename _Tp, typename... _Types> 1354 constexpr _Tp& 1355 get(tuple<_Types...>& __t) noexcept 1356 { return std::__get_helper2<_Tp>(__t); } 1357 1358 /// Return a reference to the unique element of type _Tp of a tuple rvalue. 1359 template <typename _Tp, typename... _Types> 1360 constexpr _Tp&& 1361 get(tuple<_Types...>&& __t) noexcept 1362 { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); } 1363 1364 /// Return a const reference to the unique element of type _Tp of a tuple. 1365 template <typename _Tp, typename... _Types> 1366 constexpr const _Tp& 1367 get(const tuple<_Types...>& __t) noexcept 1368 { return std::__get_helper2<_Tp>(__t); } 1369 1370 /// Return a const reference to the unique element of type _Tp of 1371 /// a const tuple rvalue. 1372 template <typename _Tp, typename... _Types> 1373 constexpr const _Tp&& 1374 get(const tuple<_Types...>&& __t) noexcept 1375 { return std::forward<const _Tp&&>(std::__get_helper2<_Tp>(__t)); } 1376#endif 1377 1378 // This class performs the comparison operations on tuples 1379 template<typename _Tp, typename _Up, size_t __i, size_t __size> 1380 struct __tuple_compare 1381 { 1382 static constexpr bool 1383 __eq(const _Tp& __t, const _Up& __u) 1384 { 1385 return bool(std::get<__i>(__t) == std::get<__i>(__u)) 1386 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u); 1387 } 1388 1389 static constexpr bool 1390 __less(const _Tp& __t, const _Up& __u) 1391 { 1392 return bool(std::get<__i>(__t) < std::get<__i>(__u)) 1393 || (!bool(std::get<__i>(__u) < std::get<__i>(__t)) 1394 && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u)); 1395 } 1396 }; 1397 1398 template<typename _Tp, typename _Up, size_t __size> 1399 struct __tuple_compare<_Tp, _Up, __size, __size> 1400 { 1401 static constexpr bool 1402 __eq(const _Tp&, const _Up&) { return true; } 1403 1404 static constexpr bool 1405 __less(const _Tp&, const _Up&) { return false; } 1406 }; 1407 1408 template<typename... _TElements, typename... _UElements> 1409 constexpr bool 1410 operator==(const tuple<_TElements...>& __t, 1411 const tuple<_UElements...>& __u) 1412 { 1413 static_assert(sizeof...(_TElements) == sizeof...(_UElements), 1414 "tuple objects can only be compared if they have equal sizes."); 1415 using __compare = __tuple_compare<tuple<_TElements...>, 1416 tuple<_UElements...>, 1417 0, sizeof...(_TElements)>; 1418 return __compare::__eq(__t, __u); 1419 } 1420 1421#if __cpp_lib_three_way_comparison 1422 template<typename _Cat, typename _Tp, typename _Up> 1423 constexpr _Cat 1424 __tuple_cmp(const _Tp&, const _Up&, index_sequence<>) 1425 { return _Cat::equivalent; } 1426 1427 template<typename _Cat, typename _Tp, typename _Up, 1428 size_t _Idx0, size_t... _Idxs> 1429 constexpr _Cat 1430 __tuple_cmp(const _Tp& __t, const _Up& __u, 1431 index_sequence<_Idx0, _Idxs...>) 1432 { 1433 auto __c 1434 = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u)); 1435 if (__c != 0) 1436 return __c; 1437 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>()); 1438 } 1439 1440 template<typename... _Tps, typename... _Ups> 1441 constexpr 1442 common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...> 1443 operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u) 1444 { 1445 using _Cat 1446 = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>; 1447 return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>()); 1448 } 1449#else 1450 template<typename... _TElements, typename... _UElements> 1451 constexpr bool 1452 operator<(const tuple<_TElements...>& __t, 1453 const tuple<_UElements...>& __u) 1454 { 1455 static_assert(sizeof...(_TElements) == sizeof...(_UElements), 1456 "tuple objects can only be compared if they have equal sizes."); 1457 using __compare = __tuple_compare<tuple<_TElements...>, 1458 tuple<_UElements...>, 1459 0, sizeof...(_TElements)>; 1460 return __compare::__less(__t, __u); 1461 } 1462 1463 template<typename... _TElements, typename... _UElements> 1464 constexpr bool 1465 operator!=(const tuple<_TElements...>& __t, 1466 const tuple<_UElements...>& __u) 1467 { return !(__t == __u); } 1468 1469 template<typename... _TElements, typename... _UElements> 1470 constexpr bool 1471 operator>(const tuple<_TElements...>& __t, 1472 const tuple<_UElements...>& __u) 1473 { return __u < __t; } 1474 1475 template<typename... _TElements, typename... _UElements> 1476 constexpr bool 1477 operator<=(const tuple<_TElements...>& __t, 1478 const tuple<_UElements...>& __u) 1479 { return !(__u < __t); } 1480 1481 template<typename... _TElements, typename... _UElements> 1482 constexpr bool 1483 operator>=(const tuple<_TElements...>& __t, 1484 const tuple<_UElements...>& __u) 1485 { return !(__t < __u); } 1486#endif // three_way_comparison 1487 1488 // NB: DR 705. 1489 template<typename... _Elements> 1490 constexpr tuple<typename __decay_and_strip<_Elements>::__type...> 1491 make_tuple(_Elements&&... __args) 1492 { 1493 typedef tuple<typename __decay_and_strip<_Elements>::__type...> 1494 __result_type; 1495 return __result_type(std::forward<_Elements>(__args)...); 1496 } 1497 1498 // _GLIBCXX_RESOLVE_LIB_DEFECTS 1499 // 2275. Why is forward_as_tuple not constexpr? 1500 /// std::forward_as_tuple 1501 template<typename... _Elements> 1502 constexpr tuple<_Elements&&...> 1503 forward_as_tuple(_Elements&&... __args) noexcept 1504 { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); } 1505 1506 template<size_t, typename, typename, size_t> 1507 struct __make_tuple_impl; 1508 1509 template<size_t _Idx, typename _Tuple, typename... _Tp, size_t _Nm> 1510 struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm> 1511 : __make_tuple_impl<_Idx + 1, 1512 tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>, 1513 _Tuple, _Nm> 1514 { }; 1515 1516 template<std::size_t _Nm, typename _Tuple, typename... _Tp> 1517 struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm> 1518 { 1519 typedef tuple<_Tp...> __type; 1520 }; 1521 1522 template<typename _Tuple> 1523 struct __do_make_tuple 1524 : __make_tuple_impl<0, tuple<>, _Tuple, std::tuple_size<_Tuple>::value> 1525 { }; 1526 1527 // Returns the std::tuple equivalent of a tuple-like type. 1528 template<typename _Tuple> 1529 struct __make_tuple 1530 : public __do_make_tuple<__remove_cvref_t<_Tuple>> 1531 { }; 1532 1533 // Combines several std::tuple's into a single one. 1534 template<typename...> 1535 struct __combine_tuples; 1536 1537 template<> 1538 struct __combine_tuples<> 1539 { 1540 typedef tuple<> __type; 1541 }; 1542 1543 template<typename... _Ts> 1544 struct __combine_tuples<tuple<_Ts...>> 1545 { 1546 typedef tuple<_Ts...> __type; 1547 }; 1548 1549 template<typename... _T1s, typename... _T2s, typename... _Rem> 1550 struct __combine_tuples<tuple<_T1s...>, tuple<_T2s...>, _Rem...> 1551 { 1552 typedef typename __combine_tuples<tuple<_T1s..., _T2s...>, 1553 _Rem...>::__type __type; 1554 }; 1555 1556 // Computes the result type of tuple_cat given a set of tuple-like types. 1557 template<typename... _Tpls> 1558 struct __tuple_cat_result 1559 { 1560 typedef typename __combine_tuples 1561 <typename __make_tuple<_Tpls>::__type...>::__type __type; 1562 }; 1563 1564 // Helper to determine the index set for the first tuple-like 1565 // type of a given set. 1566 template<typename...> 1567 struct __make_1st_indices; 1568 1569 template<> 1570 struct __make_1st_indices<> 1571 { 1572 typedef std::_Index_tuple<> __type; 1573 }; 1574 1575 template<typename _Tp, typename... _Tpls> 1576 struct __make_1st_indices<_Tp, _Tpls...> 1577 { 1578 typedef typename std::_Build_index_tuple<std::tuple_size< 1579 typename std::remove_reference<_Tp>::type>::value>::__type __type; 1580 }; 1581 1582 // Performs the actual concatenation by step-wise expanding tuple-like 1583 // objects into the elements, which are finally forwarded into the 1584 // result tuple. 1585 template<typename _Ret, typename _Indices, typename... _Tpls> 1586 struct __tuple_concater; 1587 1588 template<typename _Ret, std::size_t... _Is, typename _Tp, typename... _Tpls> 1589 struct __tuple_concater<_Ret, std::_Index_tuple<_Is...>, _Tp, _Tpls...> 1590 { 1591 template<typename... _Us> 1592 static constexpr _Ret 1593 _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us) 1594 { 1595 typedef typename __make_1st_indices<_Tpls...>::__type __idx; 1596 typedef __tuple_concater<_Ret, __idx, _Tpls...> __next; 1597 return __next::_S_do(std::forward<_Tpls>(__tps)..., 1598 std::forward<_Us>(__us)..., 1599 std::get<_Is>(std::forward<_Tp>(__tp))...); 1600 } 1601 }; 1602 1603 template<typename _Ret> 1604 struct __tuple_concater<_Ret, std::_Index_tuple<>> 1605 { 1606 template<typename... _Us> 1607 static constexpr _Ret 1608 _S_do(_Us&&... __us) 1609 { 1610 return _Ret(std::forward<_Us>(__us)...); 1611 } 1612 }; 1613 1614 /// tuple_cat 1615 template<typename... _Tpls, typename = typename 1616 enable_if<__and_<__is_tuple_like<_Tpls>...>::value>::type> 1617 constexpr auto 1618 tuple_cat(_Tpls&&... __tpls) 1619 -> typename __tuple_cat_result<_Tpls...>::__type 1620 { 1621 typedef typename __tuple_cat_result<_Tpls...>::__type __ret; 1622 typedef typename __make_1st_indices<_Tpls...>::__type __idx; 1623 typedef __tuple_concater<__ret, __idx, _Tpls...> __concater; 1624 return __concater::_S_do(std::forward<_Tpls>(__tpls)...); 1625 } 1626 1627 // _GLIBCXX_RESOLVE_LIB_DEFECTS 1628 // 2301. Why is tie not constexpr? 1629 /// tie 1630 template<typename... _Elements> 1631 constexpr tuple<_Elements&...> 1632 tie(_Elements&... __args) noexcept 1633 { return tuple<_Elements&...>(__args...); } 1634 1635 /// swap 1636 template<typename... _Elements> 1637 _GLIBCXX20_CONSTEXPR 1638 inline 1639#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 1640 // Constrained free swap overload, see p0185r1 1641 typename enable_if<__and_<__is_swappable<_Elements>...>::value 1642 >::type 1643#else 1644 void 1645#endif 1646 swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y) 1647 noexcept(noexcept(__x.swap(__y))) 1648 { __x.swap(__y); } 1649 1650#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 1651 template<typename... _Elements> 1652 _GLIBCXX20_CONSTEXPR 1653 typename enable_if<!__and_<__is_swappable<_Elements>...>::value>::type 1654 swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete; 1655#endif 1656 1657 // A class (and instance) which can be used in 'tie' when an element 1658 // of a tuple is not required. 1659 // _GLIBCXX14_CONSTEXPR 1660 // 2933. PR for LWG 2773 could be clearer 1661 struct _Swallow_assign 1662 { 1663 template<class _Tp> 1664 _GLIBCXX14_CONSTEXPR const _Swallow_assign& 1665 operator=(const _Tp&) const 1666 { return *this; } 1667 }; 1668 1669 // _GLIBCXX_RESOLVE_LIB_DEFECTS 1670 // 2773. Making std::ignore constexpr 1671 _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{}; 1672 1673 /// Partial specialization for tuples 1674 template<typename... _Types, typename _Alloc> 1675 struct uses_allocator<tuple<_Types...>, _Alloc> : true_type { }; 1676 1677 // See stl_pair.h... 1678 /** "piecewise construction" using a tuple of arguments for each member. 1679 * 1680 * @param __first Arguments for the first member of the pair. 1681 * @param __second Arguments for the second member of the pair. 1682 * 1683 * The elements of each tuple will be used as the constructor arguments 1684 * for the data members of the pair. 1685 */ 1686 template<class _T1, class _T2> 1687 template<typename... _Args1, typename... _Args2> 1688 _GLIBCXX20_CONSTEXPR 1689 inline 1690 pair<_T1, _T2>:: 1691 pair(piecewise_construct_t, 1692 tuple<_Args1...> __first, tuple<_Args2...> __second) 1693 : pair(__first, __second, 1694 typename _Build_index_tuple<sizeof...(_Args1)>::__type(), 1695 typename _Build_index_tuple<sizeof...(_Args2)>::__type()) 1696 { } 1697 1698 template<class _T1, class _T2> 1699 template<typename... _Args1, std::size_t... _Indexes1, 1700 typename... _Args2, std::size_t... _Indexes2> 1701 _GLIBCXX20_CONSTEXPR inline 1702 pair<_T1, _T2>:: 1703 pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2, 1704 _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>) 1705 : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...), 1706 second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...) 1707 { } 1708 1709#if __cplusplus >= 201703L 1710 1711 // Unpack a std::tuple into a type trait and use its value. 1712 // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value. 1713 // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value. 1714 // Otherwise the result is false (because we don't know if std::get throws). 1715 template<template<typename...> class _Trait, typename _Tp, typename _Tuple> 1716 inline constexpr bool __unpack_std_tuple = false; 1717 1718 template<template<typename...> class _Trait, typename _Tp, typename... _Up> 1719 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>> 1720 = _Trait<_Tp, _Up...>::value; 1721 1722 template<template<typename...> class _Trait, typename _Tp, typename... _Up> 1723 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&> 1724 = _Trait<_Tp, _Up&...>::value; 1725 1726 template<template<typename...> class _Trait, typename _Tp, typename... _Up> 1727 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>> 1728 = _Trait<_Tp, const _Up...>::value; 1729 1730 template<template<typename...> class _Trait, typename _Tp, typename... _Up> 1731 inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&> 1732 = _Trait<_Tp, const _Up&...>::value; 1733 1734# define __cpp_lib_apply 201603 1735 1736 template <typename _Fn, typename _Tuple, size_t... _Idx> 1737 constexpr decltype(auto) 1738 __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>) 1739 { 1740 return std::__invoke(std::forward<_Fn>(__f), 1741 std::get<_Idx>(std::forward<_Tuple>(__t))...); 1742 } 1743 1744 template <typename _Fn, typename _Tuple> 1745 constexpr decltype(auto) 1746 apply(_Fn&& __f, _Tuple&& __t) 1747 noexcept(__unpack_std_tuple<is_nothrow_invocable, _Fn, _Tuple>) 1748 { 1749 using _Indices 1750 = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>; 1751 return std::__apply_impl(std::forward<_Fn>(__f), 1752 std::forward<_Tuple>(__t), 1753 _Indices{}); 1754 } 1755 1756#define __cpp_lib_make_from_tuple 201606 1757 1758 template <typename _Tp, typename _Tuple, size_t... _Idx> 1759 constexpr _Tp 1760 __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>) 1761 { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); } 1762 1763 template <typename _Tp, typename _Tuple> 1764 constexpr _Tp 1765 make_from_tuple(_Tuple&& __t) 1766 noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>) 1767 { 1768 return __make_from_tuple_impl<_Tp>( 1769 std::forward<_Tuple>(__t), 1770 make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>{}); 1771 } 1772#endif // C++17 1773 1774 /// @} 1775 1776_GLIBCXX_END_NAMESPACE_VERSION 1777} // namespace std 1778 1779#endif // C++11 1780 1781#endif // _GLIBCXX_TUPLE 1782