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