Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/c++/15/bits/stl_pair.h
1 // Pair implementation -*- C++ -*- 2 3 // Copyright (C) 2001-2025 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /* 26 * 27 * Copyright (c) 1994 28 * Hewlett-Packard Company 29 * 30 * Permission to use, copy, modify, distribute and sell this software 31 * and its documentation for any purpose is hereby granted without fee, 32 * provided that the above copyright notice appear in all copies and 33 * that both that copyright notice and this permission notice appear 34 * in supporting documentation. Hewlett-Packard Company makes no 35 * representations about the suitability of this software for any 36 * purpose. It is provided "as is" without express or implied warranty. 37 * 38 * 39 * Copyright (c) 1996,1997 40 * Silicon Graphics Computer Systems, Inc. 41 * 42 * Permission to use, copy, modify, distribute and sell this software 43 * and its documentation for any purpose is hereby granted without fee, 44 * provided that the above copyright notice appear in all copies and 45 * that both that copyright notice and this permission notice appear 46 * in supporting documentation. Silicon Graphics makes no 47 * representations about the suitability of this software for any 48 * purpose. It is provided "as is" without express or implied warranty. 49 */ 50 51 /** @file bits/stl_pair.h 52 * This is an internal header file, included by other library headers. 53 * Do not attempt to use it directly. @headername{utility} 54 */ 55 56 #ifndef _STL_PAIR_H 57 #define _STL_PAIR_H 1 58 59 #if __cplusplus >= 201103L 60 # include <type_traits> // for std::__decay_and_strip 61 # include <bits/move.h> // for std::move / std::forward, and std::swap 62 # include <bits/utility.h> // for std::tuple_element, std::tuple_size 63 #endif 64 #if __cplusplus >= 202002L 65 # include <compare> 66 #endif 67 68 namespace std _GLIBCXX_VISIBILITY(default) 69 { 70 _GLIBCXX_BEGIN_NAMESPACE_VERSION 71 72 /** 73 * @addtogroup utilities 74 * @{ 75 */ 76 77 #if __cplusplus >= 201103L 78 /// Tag type for piecewise construction of std::pair objects. 79 struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; 80 81 /// Tag for piecewise construction of std::pair objects. 82 _GLIBCXX17_INLINE constexpr piecewise_construct_t piecewise_construct = 83 piecewise_construct_t(); 84 85 /// @cond undocumented 86 87 // Forward declarations. 88 template<typename _T1, typename _T2> 89 struct pair; 90 91 template<typename...> 92 class tuple; 93 94 // Declarations of std::array and its std::get overloads, so that 95 // std::tuple_cat can use them if <tuple> is included before <array>. 96 // We also declare the other std::get overloads here so that they're 97 // visible to the P2165R4 tuple-like constructors of pair and tuple. 98 template<typename _Tp, size_t _Nm> 99 struct array; 100 101 template<size_t...> 102 struct _Index_tuple; 103 104 template<typename _Tp> 105 class complex; 106 107 template<size_t _Int, class _Tp1, class _Tp2> 108 constexpr typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type& 109 get(pair<_Tp1, _Tp2>& __in) noexcept; 110 111 template<size_t _Int, class _Tp1, class _Tp2> 112 constexpr typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type&& 113 get(pair<_Tp1, _Tp2>&& __in) noexcept; 114 115 template<size_t _Int, class _Tp1, class _Tp2> 116 constexpr const typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type& 117 get(const pair<_Tp1, _Tp2>& __in) noexcept; 118 119 template<size_t _Int, class _Tp1, class _Tp2> 120 constexpr const typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type&& 121 get(const pair<_Tp1, _Tp2>&& __in) noexcept; 122 123 template<size_t __i, typename... _Elements> 124 constexpr __tuple_element_t<__i, tuple<_Elements...>>& 125 get(tuple<_Elements...>& __t) noexcept; 126 127 template<size_t __i, typename... _Elements> 128 constexpr const __tuple_element_t<__i, tuple<_Elements...>>& 129 get(const tuple<_Elements...>& __t) noexcept; 130 131 template<size_t __i, typename... _Elements> 132 constexpr __tuple_element_t<__i, tuple<_Elements...>>&& 133 get(tuple<_Elements...>&& __t) noexcept; 134 135 template<size_t __i, typename... _Elements> 136 constexpr const __tuple_element_t<__i, tuple<_Elements...>>&& 137 get(const tuple<_Elements...>&& __t) noexcept; 138 139 template<size_t _Int, typename _Tp, size_t _Nm> 140 constexpr _Tp& 141 get(array<_Tp, _Nm>&) noexcept; 142 143 template<size_t _Int, typename _Tp, size_t _Nm> 144 constexpr _Tp&& 145 get(array<_Tp, _Nm>&&) noexcept; 146 147 template<size_t _Int, typename _Tp, size_t _Nm> 148 constexpr const _Tp& 149 get(const array<_Tp, _Nm>&) noexcept; 150 151 template<size_t _Int, typename _Tp, size_t _Nm> 152 constexpr const _Tp&& 153 get(const array<_Tp, _Nm>&&) noexcept; 154 155 #if __glibcxx_tuple_like >= 202311 // >= C++26 156 template<size_t _Int, typename _Tp> 157 constexpr _Tp& 158 get(complex<_Tp>&) noexcept; 159 template<size_t _Int, typename _Tp> 160 constexpr _Tp&& 161 get(complex<_Tp>&&) noexcept; 162 template<size_t _Int, typename _Tp> 163 constexpr const _Tp& 164 get(const complex<_Tp>&) noexcept; 165 template<size_t _Int, typename _Tp> 166 constexpr const _Tp&& 167 get(const complex<_Tp>&&) noexcept; 168 #endif 169 170 #if ! __cpp_lib_concepts 171 // Concept utility functions, reused in conditionally-explicit 172 // constructors. 173 // See PR 70437, don't look at is_constructible or 174 // is_convertible if the types are the same to 175 // avoid querying those properties for incomplete types. 176 template <bool, typename _T1, typename _T2> 177 struct _PCC 178 { 179 template <typename _U1, typename _U2> 180 static constexpr bool _ConstructiblePair() 181 { 182 return __and_<is_constructible<_T1, const _U1&>, 183 is_constructible<_T2, const _U2&>>::value; 184 } 185 186 template <typename _U1, typename _U2> 187 static constexpr bool _ImplicitlyConvertiblePair() 188 { 189 return __and_<is_convertible<const _U1&, _T1>, 190 is_convertible<const _U2&, _T2>>::value; 191 } 192 193 template <typename _U1, typename _U2> 194 static constexpr bool _MoveConstructiblePair() 195 { 196 return __and_<is_constructible<_T1, _U1&&>, 197 is_constructible<_T2, _U2&&>>::value; 198 } 199 200 template <typename _U1, typename _U2> 201 static constexpr bool _ImplicitlyMoveConvertiblePair() 202 { 203 return __and_<is_convertible<_U1&&, _T1>, 204 is_convertible<_U2&&, _T2>>::value; 205 } 206 }; 207 208 template <typename _T1, typename _T2> 209 struct _PCC<false, _T1, _T2> 210 { 211 template <typename _U1, typename _U2> 212 static constexpr bool _ConstructiblePair() 213 { 214 return false; 215 } 216 217 template <typename _U1, typename _U2> 218 static constexpr bool _ImplicitlyConvertiblePair() 219 { 220 return false; 221 } 222 223 template <typename _U1, typename _U2> 224 static constexpr bool _MoveConstructiblePair() 225 { 226 return false; 227 } 228 229 template <typename _U1, typename _U2> 230 static constexpr bool _ImplicitlyMoveConvertiblePair() 231 { 232 return false; 233 } 234 }; 235 #endif // lib concepts 236 #endif // C++11 237 238 #if __glibcxx_tuple_like // >= C++23 239 template<typename _Tp> 240 inline constexpr bool __is_tuple_v = false; 241 242 template<typename... _Ts> 243 inline constexpr bool __is_tuple_v<tuple<_Ts...>> = true; 244 245 // TODO: Reuse __is_tuple_like from <type_traits>? 246 template<typename _Tp> 247 inline constexpr bool __is_tuple_like_v = false; 248 249 template<typename... _Elements> 250 inline constexpr bool __is_tuple_like_v<tuple<_Elements...>> = true; 251 252 template<typename _T1, typename _T2> 253 inline constexpr bool __is_tuple_like_v<pair<_T1, _T2>> = true; 254 255 template<typename _Tp, size_t _Nm> 256 inline constexpr bool __is_tuple_like_v<array<_Tp, _Nm>> = true; 257 258 // __is_tuple_like_v<subrange> is defined in <bits/ranges_util.h>. 259 260 template<typename _Tp> 261 concept __tuple_like = __is_tuple_like_v<remove_cvref_t<_Tp>>; 262 263 template<typename _Tp> 264 concept __pair_like = __tuple_like<_Tp> && tuple_size_v<remove_cvref_t<_Tp>> == 2; 265 266 template<typename _Tp, typename _Tuple> 267 concept __eligible_tuple_like 268 = __detail::__different_from<_Tp, _Tuple> && __tuple_like<_Tp> 269 && (tuple_size_v<remove_cvref_t<_Tp>> == tuple_size_v<_Tuple>) 270 && !ranges::__detail::__is_subrange<remove_cvref_t<_Tp>>; 271 272 template<typename _Tp, typename _Pair> 273 concept __eligible_pair_like 274 = __detail::__different_from<_Tp, _Pair> && __pair_like<_Tp> 275 && !ranges::__detail::__is_subrange<remove_cvref_t<_Tp>>; 276 #endif // C++23 277 278 template<typename _U1, typename _U2> class __pair_base 279 { 280 #if __cplusplus >= 201103L && ! __cpp_lib_concepts 281 template<typename _T1, typename _T2> friend struct pair; 282 __pair_base() = default; 283 ~__pair_base() = default; 284 __pair_base(const __pair_base&) = default; 285 __pair_base& operator=(const __pair_base&) = delete; 286 #endif // C++11 287 }; 288 289 /// @endcond 290 291 /** 292 * @brief Struct holding two objects of arbitrary type. 293 * 294 * @tparam _T1 Type of first object. 295 * @tparam _T2 Type of second object. 296 * 297 * <https://gcc.gnu.org/onlinedocs/libstdc++/manual/utilities.html> 298 * 299 * @headerfile utility 300 */ 301 template<typename _T1, typename _T2> 302 struct pair 303 : public __pair_base<_T1, _T2> 304 { 305 typedef _T1 first_type; ///< The type of the `first` member 306 typedef _T2 second_type; ///< The type of the `second` member 307 308 _T1 first; ///< The first member 309 _T2 second; ///< The second member 310 311 #if __cplusplus >= 201103L 312 constexpr pair(const pair&) = default; ///< Copy constructor 313 constexpr pair(pair&&) = default; ///< Move constructor 314 315 template<typename... _Args1, typename... _Args2> 316 _GLIBCXX20_CONSTEXPR 317 pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>); 318 319 /// Swap the first members and then the second members. 320 _GLIBCXX20_CONSTEXPR void 321 swap(pair& __p) 322 noexcept(__and_<__is_nothrow_swappable<_T1>, 323 __is_nothrow_swappable<_T2>>::value) 324 { 325 using std::swap; 326 swap(first, __p.first); 327 swap(second, __p.second); 328 } 329 330 #if __glibcxx_ranges_zip // >= C++23 331 // As an extension, we constrain the const swap member function in order 332 // to continue accepting explicit instantiation of pairs whose elements 333 // are not all const swappable. Without this constraint, such an 334 // explicit instantiation would also instantiate the ill-formed body of 335 // this function and yield a hard error. This constraint shouldn't 336 // affect the behavior of valid programs. 337 constexpr void 338 swap(const pair& __p) const 339 noexcept(__and_v<__is_nothrow_swappable<const _T1>, 340 __is_nothrow_swappable<const _T2>>) 341 requires is_swappable_v<const _T1> && is_swappable_v<const _T2> 342 { 343 using std::swap; 344 swap(first, __p.first); 345 swap(second, __p.second); 346 } 347 #endif // C++23 348 349 private: 350 template<typename... _Args1, size_t... _Indexes1, 351 typename... _Args2, size_t... _Indexes2> 352 _GLIBCXX20_CONSTEXPR 353 pair(tuple<_Args1...>&, tuple<_Args2...>&, 354 _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>); 355 public: 356 357 #if __cpp_lib_concepts 358 // C++20 implementation using concepts, explicit(bool), fully constexpr. 359 360 /// Default constructor 361 constexpr 362 explicit(__not_<__and_<__is_implicitly_default_constructible<_T1>, 363 __is_implicitly_default_constructible<_T2>>>()) 364 pair() 365 noexcept(is_nothrow_default_constructible_v<_T1> 366 && is_nothrow_default_constructible_v<_T2>) 367 requires is_default_constructible_v<_T1> 368 && is_default_constructible_v<_T2> 369 : first(), second() 370 { } 371 372 private: 373 374 /// @cond undocumented 375 template<typename _U1, typename _U2> 376 static constexpr bool 377 _S_constructible() 378 { 379 if constexpr (is_constructible_v<_T1, _U1>) 380 return is_constructible_v<_T2, _U2>; 381 return false; 382 } 383 384 template<typename _U1, typename _U2> 385 static constexpr bool 386 _S_nothrow_constructible() 387 { 388 if constexpr (is_nothrow_constructible_v<_T1, _U1>) 389 return is_nothrow_constructible_v<_T2, _U2>; 390 return false; 391 } 392 393 template<typename _U1, typename _U2> 394 static constexpr bool 395 _S_convertible() 396 { 397 if constexpr (is_convertible_v<_U1, _T1>) 398 return is_convertible_v<_U2, _T2>; 399 return false; 400 } 401 402 // True if construction from _U1 and _U2 would create a dangling ref. 403 template<typename _U1, typename _U2> 404 static constexpr bool 405 _S_dangles() 406 { 407 #if __has_builtin(__reference_constructs_from_temporary) 408 if constexpr (__reference_constructs_from_temporary(_T1, _U1&&)) 409 return true; 410 else 411 return __reference_constructs_from_temporary(_T2, _U2&&); 412 #else 413 return false; 414 #endif 415 } 416 417 #if __glibcxx_tuple_like // >= C++23 418 template<typename _UPair> 419 static constexpr bool 420 _S_constructible_from_pair_like() 421 { 422 return _S_constructible<decltype(std::get<0>(std::declval<_UPair>())), 423 decltype(std::get<1>(std::declval<_UPair>()))>(); 424 } 425 426 template<typename _UPair> 427 static constexpr bool 428 _S_convertible_from_pair_like() 429 { 430 return _S_convertible<decltype(std::get<0>(std::declval<_UPair>())), 431 decltype(std::get<1>(std::declval<_UPair>()))>(); 432 } 433 434 template<typename _UPair> 435 static constexpr bool 436 _S_dangles_from_pair_like() 437 { 438 return _S_dangles<decltype(std::get<0>(std::declval<_UPair>())), 439 decltype(std::get<1>(std::declval<_UPair>()))>(); 440 } 441 #endif // C++23 442 /// @endcond 443 444 public: 445 446 /// Constructor accepting lvalues of `first_type` and `second_type` 447 constexpr explicit(!_S_convertible<const _T1&, const _T2&>()) 448 pair(const type_identity_t<_T1>& __x, const _T2& __y) 449 noexcept(_S_nothrow_constructible<const _T1&, const _T2&>()) 450 requires (_S_constructible<const _T1&, const _T2&>()) 451 : first(__x), second(__y) 452 { } 453 454 /// Constructor accepting two values of arbitrary types 455 #if __cplusplus > 202002L 456 template<typename _U1 = _T1, typename _U2 = _T2> 457 #else 458 template<typename _U1, typename _U2> 459 #endif 460 requires (_S_constructible<_U1, _U2>()) && (!_S_dangles<_U1, _U2>()) 461 constexpr explicit(!_S_convertible<_U1, _U2>()) 462 pair(_U1&& __x, _U2&& __y) 463 noexcept(_S_nothrow_constructible<_U1, _U2>()) 464 : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) 465 { } 466 467 #if __cplusplus > 202002L 468 template<typename _U1 = _T1, typename _U2 = _T2> 469 #else 470 template<typename _U1, typename _U2> 471 #endif 472 requires (_S_constructible<_U1, _U2>()) && (_S_dangles<_U1, _U2>()) 473 constexpr explicit(!_S_convertible<_U1, _U2>()) 474 pair(_U1&&, _U2&&) = delete; 475 476 /// Converting constructor from a const `pair<U1, U2>` lvalue 477 template<typename _U1, typename _U2> 478 requires (_S_constructible<const _U1&, const _U2&>()) 479 && (!_S_dangles<_U1, _U2>()) 480 constexpr explicit(!_S_convertible<const _U1&, const _U2&>()) 481 pair(const pair<_U1, _U2>& __p) 482 noexcept(_S_nothrow_constructible<const _U1&, const _U2&>()) 483 : first(__p.first), second(__p.second) 484 { } 485 486 template<typename _U1, typename _U2> 487 requires (_S_constructible<const _U1&, const _U2&>()) 488 && (_S_dangles<const _U1&, const _U2&>()) 489 constexpr explicit(!_S_convertible<const _U1&, const _U2&>()) 490 pair(const pair<_U1, _U2>&) = delete; 491 492 /// Converting constructor from a non-const `pair<U1, U2>` rvalue 493 template<typename _U1, typename _U2> 494 requires (_S_constructible<_U1, _U2>()) && (!_S_dangles<_U1, _U2>()) 495 constexpr explicit(!_S_convertible<_U1, _U2>()) 496 pair(pair<_U1, _U2>&& __p) 497 noexcept(_S_nothrow_constructible<_U1, _U2>()) 498 : first(std::forward<_U1>(__p.first)), 499 second(std::forward<_U2>(__p.second)) 500 { } 501 502 template<typename _U1, typename _U2> 503 requires (_S_constructible<_U1, _U2>()) && (_S_dangles<_U1, _U2>()) 504 constexpr explicit(!_S_convertible<_U1, _U2>()) 505 pair(pair<_U1, _U2>&&) = delete; 506 507 #if __glibcxx_ranges_zip // >= C++23 508 /// Converting constructor from a non-const `pair<U1, U2>` lvalue 509 template<typename _U1, typename _U2> 510 requires (_S_constructible<_U1&, _U2&>()) && (!_S_dangles<_U1&, _U2&>()) 511 constexpr explicit(!_S_convertible<_U1&, _U2&>()) 512 pair(pair<_U1, _U2>& __p) 513 noexcept(_S_nothrow_constructible<_U1&, _U2&>()) 514 : first(__p.first), second(__p.second) 515 { } 516 517 template<typename _U1, typename _U2> 518 requires (_S_constructible<_U1&, _U2&>()) && (_S_dangles<_U1&, _U2&>()) 519 constexpr explicit(!_S_convertible<_U1&, _U2&>()) 520 pair(pair<_U1, _U2>&) = delete; 521 522 /// Converting constructor from a const `pair<U1, U2>` rvalue 523 template<typename _U1, typename _U2> 524 requires (_S_constructible<const _U1, const _U2>()) 525 && (!_S_dangles<const _U1, const _U2>()) 526 constexpr explicit(!_S_convertible<const _U1, const _U2>()) 527 pair(const pair<_U1, _U2>&& __p) 528 noexcept(_S_nothrow_constructible<const _U1, const _U2>()) 529 : first(std::forward<const _U1>(__p.first)), 530 second(std::forward<const _U2>(__p.second)) 531 { } 532 533 template<typename _U1, typename _U2> 534 requires (_S_constructible<const _U1, const _U2>()) 535 && (_S_dangles<const _U1, const _U2>()) 536 constexpr explicit(!_S_convertible<const _U1, const _U2>()) 537 pair(const pair<_U1, _U2>&&) = delete; 538 #endif // C++23 539 540 #if __glibcxx_tuple_like // >= C++23 541 template<__eligible_pair_like<pair> _UPair> 542 requires (_S_constructible_from_pair_like<_UPair>()) 543 && (!_S_dangles_from_pair_like<_UPair>()) 544 constexpr explicit(!_S_convertible_from_pair_like<_UPair>()) 545 pair(_UPair&& __p) 546 : first(std::get<0>(std::forward<_UPair>(__p))), 547 second(std::get<1>(std::forward<_UPair>(__p))) 548 { } 549 550 template<__eligible_pair_like<pair> _UPair> 551 requires (_S_constructible_from_pair_like<_UPair>()) 552 && (_S_dangles_from_pair_like<_UPair>()) 553 constexpr explicit(!_S_convertible_from_pair_like<_UPair>()) 554 pair(_UPair&&) = delete; 555 #endif // C++23 556 557 private: 558 /// @cond undocumented 559 template<typename _U1, typename _U2> 560 static constexpr bool 561 _S_assignable() 562 { 563 if constexpr (is_assignable_v<_T1&, _U1>) 564 return is_assignable_v<_T2&, _U2>; 565 return false; 566 } 567 568 template<typename _U1, typename _U2> 569 static constexpr bool 570 _S_const_assignable() 571 { 572 if constexpr (is_assignable_v<const _T1&, _U1>) 573 return is_assignable_v<const _T2&, _U2>; 574 return false; 575 } 576 577 template<typename _U1, typename _U2> 578 static constexpr bool 579 _S_nothrow_assignable() 580 { 581 if constexpr (is_nothrow_assignable_v<_T1&, _U1>) 582 return is_nothrow_assignable_v<_T2&, _U2>; 583 return false; 584 } 585 586 #if __glibcxx_tuple_like // >= C++23 587 template<typename _UPair> 588 static constexpr bool 589 _S_assignable_from_tuple_like() 590 { 591 return _S_assignable<decltype(std::get<0>(std::declval<_UPair>())), 592 decltype(std::get<1>(std::declval<_UPair>()))>(); 593 } 594 595 template<typename _UPair> 596 static constexpr bool 597 _S_const_assignable_from_tuple_like() 598 { 599 return _S_const_assignable<decltype(std::get<0>(std::declval<_UPair>())), 600 decltype(std::get<1>(std::declval<_UPair>()))>(); 601 } 602 #endif // C++23 603 /// @endcond 604 605 public: 606 607 pair& operator=(const pair&) = delete; 608 609 /// Copy assignment operator 610 constexpr pair& 611 operator=(const pair& __p) 612 noexcept(_S_nothrow_assignable<const _T1&, const _T2&>()) 613 requires (_S_assignable<const _T1&, const _T2&>()) 614 { 615 first = __p.first; 616 second = __p.second; 617 return *this; 618 } 619 620 /// Move assignment operator 621 constexpr pair& 622 operator=(pair&& __p) 623 noexcept(_S_nothrow_assignable<_T1, _T2>()) 624 requires (_S_assignable<_T1, _T2>()) 625 { 626 first = std::forward<first_type>(__p.first); 627 second = std::forward<second_type>(__p.second); 628 return *this; 629 } 630 631 /// Converting assignment from a const `pair<U1, U2>` lvalue 632 template<typename _U1, typename _U2> 633 constexpr pair& 634 operator=(const pair<_U1, _U2>& __p) 635 noexcept(_S_nothrow_assignable<const _U1&, const _U2&>()) 636 requires (_S_assignable<const _U1&, const _U2&>()) 637 { 638 first = __p.first; 639 second = __p.second; 640 return *this; 641 } 642 643 /// Converting assignment from a non-const `pair<U1, U2>` rvalue 644 template<typename _U1, typename _U2> 645 constexpr pair& 646 operator=(pair<_U1, _U2>&& __p) 647 noexcept(_S_nothrow_assignable<_U1, _U2>()) 648 requires (_S_assignable<_U1, _U2>()) 649 { 650 first = std::forward<_U1>(__p.first); 651 second = std::forward<_U2>(__p.second); 652 return *this; 653 } 654 655 #if __glibcxx_ranges_zip // >= C++23 656 /// Copy assignment operator (const) 657 constexpr const pair& 658 operator=(const pair& __p) const 659 requires (_S_const_assignable<const first_type&, const second_type&>()) 660 { 661 first = __p.first; 662 second = __p.second; 663 return *this; 664 } 665 666 /// Move assignment operator (const) 667 constexpr const pair& 668 operator=(pair&& __p) const 669 requires (_S_const_assignable<first_type, second_type>()) 670 { 671 first = std::forward<first_type>(__p.first); 672 second = std::forward<second_type>(__p.second); 673 return *this; 674 } 675 676 /// Converting assignment from a const `pair<U1, U2>` lvalue 677 template<typename _U1, typename _U2> 678 constexpr const pair& 679 operator=(const pair<_U1, _U2>& __p) const 680 requires (_S_const_assignable<const _U1&, const _U2&>()) 681 { 682 first = __p.first; 683 second = __p.second; 684 return *this; 685 } 686 687 /// Converting assignment from a non-const `pair<U1, U2>` rvalue 688 template<typename _U1, typename _U2> 689 constexpr const pair& 690 operator=(pair<_U1, _U2>&& __p) const 691 requires (_S_const_assignable<_U1, _U2>()) 692 { 693 first = std::forward<_U1>(__p.first); 694 second = std::forward<_U2>(__p.second); 695 return *this; 696 } 697 #endif // C++23 698 699 #if __glibcxx_tuple_like // >= C++23 700 template<__eligible_pair_like<pair> _UPair> 701 requires (_S_assignable_from_tuple_like<_UPair>()) 702 constexpr pair& 703 operator=(_UPair&& __p) 704 { 705 first = std::get<0>(std::forward<_UPair>(__p)); 706 second = std::get<1>(std::forward<_UPair>(__p)); 707 return *this; 708 } 709 710 template<__eligible_pair_like<pair> _UPair> 711 requires (_S_const_assignable_from_tuple_like<_UPair>()) 712 constexpr const pair& 713 operator=(_UPair&& __p) const 714 { 715 first = std::get<0>(std::forward<_UPair>(__p)); 716 second = std::get<1>(std::forward<_UPair>(__p)); 717 return *this; 718 } 719 #endif // C++23 720 721 #else // !__cpp_lib_concepts 722 // C++11/14/17 implementation using enable_if, partially constexpr. 723 724 /// @cond undocumented 725 // Error if construction from _U1 and _U2 would create a dangling ref. 726 #if __has_builtin(__reference_constructs_from_temporary) \ 727 && defined _GLIBCXX_DEBUG 728 # define __glibcxx_no_dangling_refs(_U1, _U2) \ 729 static_assert(!__reference_constructs_from_temporary(_T1, _U1) \ 730 && !__reference_constructs_from_temporary(_T2, _U2), \ 731 "std::pair constructor creates a dangling reference") 732 #else 733 # define __glibcxx_no_dangling_refs(_U1, _U2) 734 #endif 735 /// @endcond 736 737 /** The default constructor creates @c first and @c second using their 738 * respective default constructors. */ 739 template <typename _U1 = _T1, 740 typename _U2 = _T2, 741 typename enable_if<__and_< 742 __is_implicitly_default_constructible<_U1>, 743 __is_implicitly_default_constructible<_U2>> 744 ::value, bool>::type = true> 745 constexpr pair() 746 : first(), second() { } 747 748 template <typename _U1 = _T1, 749 typename _U2 = _T2, 750 typename enable_if<__and_< 751 is_default_constructible<_U1>, 752 is_default_constructible<_U2>, 753 __not_< 754 __and_<__is_implicitly_default_constructible<_U1>, 755 __is_implicitly_default_constructible<_U2>>>> 756 ::value, bool>::type = false> 757 explicit constexpr pair() 758 : first(), second() { } 759 760 // Shortcut for constraining the templates that don't take pairs. 761 /// @cond undocumented 762 using _PCCP = _PCC<true, _T1, _T2>; 763 /// @endcond 764 765 /// Construct from two const lvalues, allowing implicit conversions. 766 template<typename _U1 = _T1, typename _U2=_T2, typename 767 enable_if<_PCCP::template 768 _ConstructiblePair<_U1, _U2>() 769 && _PCCP::template 770 _ImplicitlyConvertiblePair<_U1, _U2>(), 771 bool>::type=true> 772 constexpr pair(const _T1& __a, const _T2& __b) 773 : first(__a), second(__b) { } 774 775 /// Construct from two const lvalues, disallowing implicit conversions. 776 template<typename _U1 = _T1, typename _U2=_T2, typename 777 enable_if<_PCCP::template 778 _ConstructiblePair<_U1, _U2>() 779 && !_PCCP::template 780 _ImplicitlyConvertiblePair<_U1, _U2>(), 781 bool>::type=false> 782 explicit constexpr pair(const _T1& __a, const _T2& __b) 783 : first(__a), second(__b) { } 784 785 // Shortcut for constraining the templates that take pairs. 786 /// @cond undocumented 787 template <typename _U1, typename _U2> 788 using _PCCFP = _PCC<!is_same<_T1, _U1>::value 789 || !is_same<_T2, _U2>::value, 790 _T1, _T2>; 791 /// @endcond 792 793 template<typename _U1, typename _U2, typename 794 enable_if<_PCCFP<_U1, _U2>::template 795 _ConstructiblePair<_U1, _U2>() 796 && _PCCFP<_U1, _U2>::template 797 _ImplicitlyConvertiblePair<_U1, _U2>(), 798 bool>::type=true> 799 constexpr pair(const pair<_U1, _U2>& __p) 800 : first(__p.first), second(__p.second) 801 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); } 802 803 template<typename _U1, typename _U2, typename 804 enable_if<_PCCFP<_U1, _U2>::template 805 _ConstructiblePair<_U1, _U2>() 806 && !_PCCFP<_U1, _U2>::template 807 _ImplicitlyConvertiblePair<_U1, _U2>(), 808 bool>::type=false> 809 explicit constexpr pair(const pair<_U1, _U2>& __p) 810 : first(__p.first), second(__p.second) 811 { __glibcxx_no_dangling_refs(const _U1&, const _U2&); } 812 813 #if _GLIBCXX_USE_DEPRECATED 814 #if defined(__DEPRECATED) 815 # define _GLIBCXX_DEPRECATED_PAIR_CTOR \ 816 __attribute__ ((__deprecated__ ("use 'nullptr' instead of '0' to " \ 817 "initialize std::pair of move-only " \ 818 "type and pointer"))) 819 #else 820 # define _GLIBCXX_DEPRECATED_PAIR_CTOR 821 #endif 822 823 private: 824 /// @cond undocumented 825 826 // A type which can be constructed from literal zero, but not nullptr 827 struct __zero_as_null_pointer_constant 828 { 829 __zero_as_null_pointer_constant(int __zero_as_null_pointer_constant::*) 830 { } 831 template<typename _Tp, 832 typename = __enable_if_t<is_null_pointer<_Tp>::value>> 833 __zero_as_null_pointer_constant(_Tp) = delete; 834 }; 835 /// @endcond 836 public: 837 838 // Deprecated extensions to DR 811. 839 // These allow construction from an rvalue and a literal zero, 840 // in cases where the standard says the zero should be deduced as int 841 template<typename _U1, 842 __enable_if_t<__and_<__not_<is_reference<_U1>>, 843 is_pointer<_T2>, 844 is_constructible<_T1, _U1>, 845 __not_<is_constructible<_T1, const _U1&>>, 846 is_convertible<_U1, _T1>>::value, 847 bool> = true> 848 _GLIBCXX_DEPRECATED_PAIR_CTOR 849 constexpr 850 pair(_U1&& __x, __zero_as_null_pointer_constant, ...) 851 : first(std::forward<_U1>(__x)), second(nullptr) 852 { __glibcxx_no_dangling_refs(_U1&&, std::nullptr_t); } 853 854 template<typename _U1, 855 __enable_if_t<__and_<__not_<is_reference<_U1>>, 856 is_pointer<_T2>, 857 is_constructible<_T1, _U1>, 858 __not_<is_constructible<_T1, const _U1&>>, 859 __not_<is_convertible<_U1, _T1>>>::value, 860 bool> = false> 861 _GLIBCXX_DEPRECATED_PAIR_CTOR 862 explicit constexpr 863 pair(_U1&& __x, __zero_as_null_pointer_constant, ...) 864 : first(std::forward<_U1>(__x)), second(nullptr) 865 { __glibcxx_no_dangling_refs(_U1&&, std::nullptr_t); } 866 867 template<typename _U2, 868 __enable_if_t<__and_<is_pointer<_T1>, 869 __not_<is_reference<_U2>>, 870 is_constructible<_T2, _U2>, 871 __not_<is_constructible<_T2, const _U2&>>, 872 is_convertible<_U2, _T2>>::value, 873 bool> = true> 874 _GLIBCXX_DEPRECATED_PAIR_CTOR 875 constexpr 876 pair(__zero_as_null_pointer_constant, _U2&& __y, ...) 877 : first(nullptr), second(std::forward<_U2>(__y)) 878 { __glibcxx_no_dangling_refs(std::nullptr_t, _U2&&); } 879 880 template<typename _U2, 881 __enable_if_t<__and_<is_pointer<_T1>, 882 __not_<is_reference<_U2>>, 883 is_constructible<_T2, _U2>, 884 __not_<is_constructible<_T2, const _U2&>>, 885 __not_<is_convertible<_U2, _T2>>>::value, 886 bool> = false> 887 _GLIBCXX_DEPRECATED_PAIR_CTOR 888 explicit constexpr 889 pair(__zero_as_null_pointer_constant, _U2&& __y, ...) 890 : first(nullptr), second(std::forward<_U2>(__y)) 891 { __glibcxx_no_dangling_refs(std::nullptr_t, _U2&&); } 892 #undef _GLIBCXX_DEPRECATED_PAIR_CTOR 893 #endif 894 895 template<typename _U1, typename _U2, typename 896 enable_if<_PCCP::template 897 _MoveConstructiblePair<_U1, _U2>() 898 && _PCCP::template 899 _ImplicitlyMoveConvertiblePair<_U1, _U2>(), 900 bool>::type=true> 901 constexpr pair(_U1&& __x, _U2&& __y) 902 : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) 903 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } 904 905 template<typename _U1, typename _U2, typename 906 enable_if<_PCCP::template 907 _MoveConstructiblePair<_U1, _U2>() 908 && !_PCCP::template 909 _ImplicitlyMoveConvertiblePair<_U1, _U2>(), 910 bool>::type=false> 911 explicit constexpr pair(_U1&& __x, _U2&& __y) 912 : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) 913 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } 914 915 916 template<typename _U1, typename _U2, typename 917 enable_if<_PCCFP<_U1, _U2>::template 918 _MoveConstructiblePair<_U1, _U2>() 919 && _PCCFP<_U1, _U2>::template 920 _ImplicitlyMoveConvertiblePair<_U1, _U2>(), 921 bool>::type=true> 922 constexpr pair(pair<_U1, _U2>&& __p) 923 : first(std::forward<_U1>(__p.first)), 924 second(std::forward<_U2>(__p.second)) 925 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } 926 927 template<typename _U1, typename _U2, typename 928 enable_if<_PCCFP<_U1, _U2>::template 929 _MoveConstructiblePair<_U1, _U2>() 930 && !_PCCFP<_U1, _U2>::template 931 _ImplicitlyMoveConvertiblePair<_U1, _U2>(), 932 bool>::type=false> 933 explicit constexpr pair(pair<_U1, _U2>&& __p) 934 : first(std::forward<_U1>(__p.first)), 935 second(std::forward<_U2>(__p.second)) 936 { __glibcxx_no_dangling_refs(_U1&&, _U2&&); } 937 938 #undef __glibcxx_no_dangling_refs 939 940 pair& 941 operator=(__conditional_t<__and_<is_copy_assignable<_T1>, 942 is_copy_assignable<_T2>>::value, 943 const pair&, const __nonesuch&> __p) 944 { 945 first = __p.first; 946 second = __p.second; 947 return *this; 948 } 949 950 pair& 951 operator=(__conditional_t<__and_<is_move_assignable<_T1>, 952 is_move_assignable<_T2>>::value, 953 pair&&, __nonesuch&&> __p) 954 noexcept(__and_<is_nothrow_move_assignable<_T1>, 955 is_nothrow_move_assignable<_T2>>::value) 956 { 957 first = std::forward<first_type>(__p.first); 958 second = std::forward<second_type>(__p.second); 959 return *this; 960 } 961 962 template<typename _U1, typename _U2> 963 typename enable_if<__and_<is_assignable<_T1&, const _U1&>, 964 is_assignable<_T2&, const _U2&>>::value, 965 pair&>::type 966 operator=(const pair<_U1, _U2>& __p) 967 { 968 first = __p.first; 969 second = __p.second; 970 return *this; 971 } 972 973 template<typename _U1, typename _U2> 974 typename enable_if<__and_<is_assignable<_T1&, _U1&&>, 975 is_assignable<_T2&, _U2&&>>::value, 976 pair&>::type 977 operator=(pair<_U1, _U2>&& __p) 978 { 979 first = std::forward<_U1>(__p.first); 980 second = std::forward<_U2>(__p.second); 981 return *this; 982 } 983 #endif // lib concepts 984 #else 985 // C++03 implementation 986 987 // _GLIBCXX_RESOLVE_LIB_DEFECTS 988 // 265. std::pair::pair() effects overly restrictive 989 /** The default constructor creates @c first and @c second using their 990 * respective default constructors. */ 991 pair() : first(), second() { } 992 993 /// Two objects may be passed to a `pair` constructor to be copied. 994 pair(const _T1& __a, const _T2& __b) 995 : first(__a), second(__b) { } 996 997 /// Templated constructor to convert from other pairs. 998 template<typename _U1, typename _U2> 999 pair(const pair<_U1, _U2>& __p) 1000 : first(__p.first), second(__p.second) 1001 { 1002 #if __has_builtin(__reference_constructs_from_temporary) 1003 #pragma GCC diagnostic push 1004 #pragma GCC diagnostic ignored "-Wunused-local-typedefs" 1005 typedef int _DanglingCheck1[ 1006 __reference_constructs_from_temporary(_T1, const _U1&) ? -1 : 1 1007 ]; 1008 typedef int _DanglingCheck2[ 1009 __reference_constructs_from_temporary(_T2, const _U2&) ? -1 : 1 1010 ]; 1011 #pragma GCC diagnostic pop 1012 #endif 1013 } 1014 #endif // C++11 1015 }; 1016 1017 /// @relates pair @{ 1018 1019 #if __cpp_deduction_guides >= 201606 1020 template<typename _T1, typename _T2> pair(_T1, _T2) -> pair<_T1, _T2>; 1021 #endif 1022 1023 #if __cpp_lib_three_way_comparison 1024 // _GLIBCXX_RESOLVE_LIB_DEFECTS 1025 // 3865. Sorting a range of pairs 1026 1027 /// Two pairs are equal iff their members are equal. 1028 template<typename _T1, typename _T2, typename _U1, typename _U2> 1029 [[nodiscard]] 1030 constexpr bool 1031 operator==(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) 1032 requires requires { 1033 { __x.first == __y.first } -> __detail::__boolean_testable; 1034 { __x.second == __y.second } -> __detail::__boolean_testable; 1035 } 1036 { return __x.first == __y.first && __x.second == __y.second; } 1037 1038 /** Defines a lexicographical order for pairs. 1039 * 1040 * For two pairs of comparable types, `P` is ordered before `Q` if 1041 * `P.first` is less than `Q.first`, or if `P.first` and `Q.first` 1042 * are equivalent (neither is less than the other) and `P.second` is 1043 * less than `Q.second`. 1044 */ 1045 template<typename _T1, typename _T2, typename _U1, typename _U2> 1046 [[nodiscard]] 1047 constexpr common_comparison_category_t<__detail::__synth3way_t<_T1, _U1>, 1048 __detail::__synth3way_t<_T2, _U2>> 1049 operator<=>(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) 1050 { 1051 if (auto __c = __detail::__synth3way(__x.first, __y.first); __c != 0) 1052 return __c; 1053 return __detail::__synth3way(__x.second, __y.second); 1054 } 1055 #else 1056 /// Two pairs of the same type are equal iff their members are equal. 1057 template<typename _T1, typename _T2> 1058 _GLIBCXX_NODISCARD 1059 inline _GLIBCXX_CONSTEXPR bool 1060 operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) 1061 { return __x.first == __y.first && __x.second == __y.second; } 1062 1063 /** Defines a lexicographical order for pairs. 1064 * 1065 * For two pairs of the same type, `P` is ordered before `Q` if 1066 * `P.first` is less than `Q.first`, or if `P.first` and `Q.first` 1067 * are equivalent (neither is less than the other) and `P.second` is less 1068 * than `Q.second`. 1069 */ 1070 template<typename _T1, typename _T2> 1071 _GLIBCXX_NODISCARD 1072 inline _GLIBCXX_CONSTEXPR bool 1073 operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) 1074 { return __x.first < __y.first 1075 || (!(__y.first < __x.first) && __x.second < __y.second); } 1076 1077 /// Uses @c operator== to find the result. 1078 template<typename _T1, typename _T2> 1079 _GLIBCXX_NODISCARD 1080 inline _GLIBCXX_CONSTEXPR bool 1081 operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) 1082 { return !(__x == __y); } 1083 1084 /// Uses @c operator< to find the result. 1085 template<typename _T1, typename _T2> 1086 _GLIBCXX_NODISCARD 1087 inline _GLIBCXX_CONSTEXPR bool 1088 operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) 1089 { return __y < __x; } 1090 1091 /// Uses @c operator< to find the result. 1092 template<typename _T1, typename _T2> 1093 _GLIBCXX_NODISCARD 1094 inline _GLIBCXX_CONSTEXPR bool 1095 operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) 1096 { return !(__y < __x); } 1097 1098 /// Uses @c operator< to find the result. 1099 template<typename _T1, typename _T2> 1100 _GLIBCXX_NODISCARD 1101 inline _GLIBCXX_CONSTEXPR bool 1102 operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) 1103 { return !(__x < __y); } 1104 #endif // !(three_way_comparison && concepts) 1105 1106 #if __cplusplus >= 201103L 1107 /** Swap overload for pairs. Calls std::pair::swap(). 1108 * 1109 * @note This std::swap overload is not declared in C++03 mode, 1110 * which has performance implications, e.g. see https://gcc.gnu.org/PR38466 1111 */ 1112 template<typename _T1, typename _T2> 1113 _GLIBCXX20_CONSTEXPR inline 1114 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 1115 // Constrained free swap overload, see p0185r1 1116 typename enable_if<__and_<__is_swappable<_T1>, 1117 __is_swappable<_T2>>::value>::type 1118 #else 1119 void 1120 #endif 1121 swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y) 1122 noexcept(noexcept(__x.swap(__y))) 1123 { __x.swap(__y); } 1124 1125 #if __glibcxx_ranges_zip // >= C++23 1126 template<typename _T1, typename _T2> 1127 requires is_swappable_v<const _T1> && is_swappable_v<const _T2> 1128 constexpr void 1129 swap(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) 1130 noexcept(noexcept(__x.swap(__y))) 1131 { __x.swap(__y); } 1132 #endif // C++23 1133 1134 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 1135 template<typename _T1, typename _T2> 1136 typename enable_if<!__and_<__is_swappable<_T1>, 1137 __is_swappable<_T2>>::value>::type 1138 swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete; 1139 #endif 1140 #endif // __cplusplus >= 201103L 1141 1142 /// @} relates pair 1143 1144 /** 1145 * @brief A convenience wrapper for creating a pair from two objects. 1146 * @param __x The first object. 1147 * @param __y The second object. 1148 * @return A newly-constructed pair<> object of the appropriate type. 1149 * 1150 * The C++98 standard says the objects are passed by reference-to-const, 1151 * but C++03 says they are passed by value (this was LWG issue #181). 1152 * 1153 * Since C++11 they have been passed by forwarding reference and then 1154 * forwarded to the new members of the pair. To create a pair with a 1155 * member of reference type, pass a `reference_wrapper` to this function. 1156 */ 1157 // _GLIBCXX_RESOLVE_LIB_DEFECTS 1158 // 181. make_pair() unintended behavior 1159 #if __cplusplus >= 201103L 1160 // NB: DR 706. 1161 template<typename _T1, typename _T2> 1162 constexpr pair<typename __decay_and_strip<_T1>::__type, 1163 typename __decay_and_strip<_T2>::__type> 1164 make_pair(_T1&& __x, _T2&& __y) 1165 { 1166 typedef typename __decay_and_strip<_T1>::__type __ds_type1; 1167 typedef typename __decay_and_strip<_T2>::__type __ds_type2; 1168 typedef pair<__ds_type1, __ds_type2> __pair_type; 1169 return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y)); 1170 } 1171 #else 1172 template<typename _T1, typename _T2> 1173 inline pair<_T1, _T2> 1174 make_pair(_T1 __x, _T2 __y) 1175 { return pair<_T1, _T2>(__x, __y); } 1176 #endif 1177 1178 /// @} 1179 1180 #if __cplusplus >= 201103L 1181 // Various functions which give std::pair a tuple-like interface. 1182 1183 /// @cond undocumented 1184 template<typename _T1, typename _T2> 1185 struct __is_tuple_like_impl<pair<_T1, _T2>> : true_type 1186 { }; 1187 /// @endcond 1188 1189 /// Partial specialization for std::pair 1190 template<class _Tp1, class _Tp2> 1191 struct tuple_size<pair<_Tp1, _Tp2>> 1192 : public integral_constant<size_t, 2> { }; 1193 1194 /// Partial specialization for std::pair 1195 template<class _Tp1, class _Tp2> 1196 struct tuple_element<0, pair<_Tp1, _Tp2>> 1197 { typedef _Tp1 type; }; 1198 1199 /// Partial specialization for std::pair 1200 template<class _Tp1, class _Tp2> 1201 struct tuple_element<1, pair<_Tp1, _Tp2>> 1202 { typedef _Tp2 type; }; 1203 1204 #if __cplusplus >= 201703L 1205 template<typename _Tp1, typename _Tp2> 1206 inline constexpr size_t tuple_size_v<pair<_Tp1, _Tp2>> = 2; 1207 1208 template<typename _Tp1, typename _Tp2> 1209 inline constexpr size_t tuple_size_v<const pair<_Tp1, _Tp2>> = 2; 1210 #endif 1211 1212 #if __cplusplus >= 201103L 1213 #pragma GCC diagnostic push 1214 #pragma GCC diagnostic ignored "-Wc++14-extensions" // variable templates 1215 #pragma GCC diagnostic ignored "-Wc++17-extensions" // inline variables 1216 template<typename _Tp> 1217 inline constexpr bool __is_pair = false; 1218 1219 template<typename _Tp, typename _Up> 1220 inline constexpr bool __is_pair<pair<_Tp, _Up>> = true; 1221 #pragma GCC diagnostic pop 1222 #endif 1223 1224 /// @cond undocumented 1225 template<size_t _Int> 1226 struct __pair_get; 1227 1228 template<> 1229 struct __pair_get<0> 1230 { 1231 template<typename _Tp1, typename _Tp2> 1232 static constexpr _Tp1& 1233 __get(pair<_Tp1, _Tp2>& __pair) noexcept 1234 { return __pair.first; } 1235 1236 template<typename _Tp1, typename _Tp2> 1237 static constexpr _Tp1&& 1238 __move_get(pair<_Tp1, _Tp2>&& __pair) noexcept 1239 { return std::forward<_Tp1>(__pair.first); } 1240 1241 template<typename _Tp1, typename _Tp2> 1242 static constexpr const _Tp1& 1243 __const_get(const pair<_Tp1, _Tp2>& __pair) noexcept 1244 { return __pair.first; } 1245 1246 template<typename _Tp1, typename _Tp2> 1247 static constexpr const _Tp1&& 1248 __const_move_get(const pair<_Tp1, _Tp2>&& __pair) noexcept 1249 { return std::forward<const _Tp1>(__pair.first); } 1250 }; 1251 1252 template<> 1253 struct __pair_get<1> 1254 { 1255 template<typename _Tp1, typename _Tp2> 1256 static constexpr _Tp2& 1257 __get(pair<_Tp1, _Tp2>& __pair) noexcept 1258 { return __pair.second; } 1259 1260 template<typename _Tp1, typename _Tp2> 1261 static constexpr _Tp2&& 1262 __move_get(pair<_Tp1, _Tp2>&& __pair) noexcept 1263 { return std::forward<_Tp2>(__pair.second); } 1264 1265 template<typename _Tp1, typename _Tp2> 1266 static constexpr const _Tp2& 1267 __const_get(const pair<_Tp1, _Tp2>& __pair) noexcept 1268 { return __pair.second; } 1269 1270 template<typename _Tp1, typename _Tp2> 1271 static constexpr const _Tp2&& 1272 __const_move_get(const pair<_Tp1, _Tp2>&& __pair) noexcept 1273 { return std::forward<const _Tp2>(__pair.second); } 1274 }; 1275 /// @endcond 1276 1277 /** @{ 1278 * std::get overloads for accessing members of std::pair 1279 */ 1280 1281 template<size_t _Int, class _Tp1, class _Tp2> 1282 constexpr typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type& 1283 get(pair<_Tp1, _Tp2>& __in) noexcept 1284 { return __pair_get<_Int>::__get(__in); } 1285 1286 template<size_t _Int, class _Tp1, class _Tp2> 1287 constexpr typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type&& 1288 get(pair<_Tp1, _Tp2>&& __in) noexcept 1289 { return __pair_get<_Int>::__move_get(std::move(__in)); } 1290 1291 template<size_t _Int, class _Tp1, class _Tp2> 1292 constexpr const typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type& 1293 get(const pair<_Tp1, _Tp2>& __in) noexcept 1294 { return __pair_get<_Int>::__const_get(__in); } 1295 1296 template<size_t _Int, class _Tp1, class _Tp2> 1297 constexpr const typename tuple_element<_Int, pair<_Tp1, _Tp2>>::type&& 1298 get(const pair<_Tp1, _Tp2>&& __in) noexcept 1299 { return __pair_get<_Int>::__const_move_get(std::move(__in)); } 1300 1301 1302 #ifdef __glibcxx_tuples_by_type // C++ >= 14 1303 template <typename _Tp, typename _Up> 1304 constexpr _Tp& 1305 get(pair<_Tp, _Up>& __p) noexcept 1306 { return __p.first; } 1307 1308 template <typename _Tp, typename _Up> 1309 constexpr const _Tp& 1310 get(const pair<_Tp, _Up>& __p) noexcept 1311 { return __p.first; } 1312 1313 template <typename _Tp, typename _Up> 1314 constexpr _Tp&& 1315 get(pair<_Tp, _Up>&& __p) noexcept 1316 { return std::forward<_Tp>(__p.first); } 1317 1318 template <typename _Tp, typename _Up> 1319 constexpr const _Tp&& 1320 get(const pair<_Tp, _Up>&& __p) noexcept 1321 { return std::forward<const _Tp>(__p.first); } 1322 1323 template <typename _Tp, typename _Up> 1324 constexpr _Tp& 1325 get(pair<_Up, _Tp>& __p) noexcept 1326 { return __p.second; } 1327 1328 template <typename _Tp, typename _Up> 1329 constexpr const _Tp& 1330 get(const pair<_Up, _Tp>& __p) noexcept 1331 { return __p.second; } 1332 1333 template <typename _Tp, typename _Up> 1334 constexpr _Tp&& 1335 get(pair<_Up, _Tp>&& __p) noexcept 1336 { return std::forward<_Tp>(__p.second); } 1337 1338 template <typename _Tp, typename _Up> 1339 constexpr const _Tp&& 1340 get(const pair<_Up, _Tp>&& __p) noexcept 1341 { return std::forward<const _Tp>(__p.second); } 1342 #endif // __glibcxx_tuples_by_type 1343 1344 1345 #if __glibcxx_ranges_zip // >= C++23 1346 template<typename _T1, typename _T2, typename _U1, typename _U2, 1347 template<typename> class _TQual, template<typename> class _UQual> 1348 requires requires { typename pair<common_reference_t<_TQual<_T1>, _UQual<_U1>>, 1349 common_reference_t<_TQual<_T2>, _UQual<_U2>>>; } 1350 struct basic_common_reference<pair<_T1, _T2>, pair<_U1, _U2>, _TQual, _UQual> 1351 { 1352 using type = pair<common_reference_t<_TQual<_T1>, _UQual<_U1>>, 1353 common_reference_t<_TQual<_T2>, _UQual<_U2>>>; 1354 }; 1355 1356 template<typename _T1, typename _T2, typename _U1, typename _U2> 1357 requires requires { typename pair<common_type_t<_T1, _U1>, common_type_t<_T2, _U2>>; } 1358 struct common_type<pair<_T1, _T2>, pair<_U1, _U2>> 1359 { using type = pair<common_type_t<_T1, _U1>, common_type_t<_T2, _U2>>; }; 1360 #endif // C++23 1361 1362 /// @} 1363 #endif // C++11 1364 1365 _GLIBCXX_END_NAMESPACE_VERSION 1366 } // namespace std 1367 1368 #endif /* _STL_PAIR_H */