1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef _LIBCPP___UTILITY_PAIR_H
10#define _LIBCPP___UTILITY_PAIR_H
11
12#include <__compare/common_comparison_category.h>
13#include <__compare/synth_three_way.h>
14#include <__concepts/boolean_testable.h>
15#include <__concepts/different_from.h>
16#include <__config>
17#include <__cstddef/size_t.h>
18#include <__fwd/array.h>
19#include <__fwd/pair.h>
20#include <__fwd/tuple.h>
21#include <__tuple/tuple_like_no_subrange.h>
22#include <__tuple/tuple_size.h>
23#include <__type_traits/common_reference.h>
24#include <__type_traits/common_type.h>
25#include <__type_traits/conditional.h>
26#include <__type_traits/enable_if.h>
27#include <__type_traits/integral_constant.h>
28#include <__type_traits/is_assignable.h>
29#include <__type_traits/is_constructible.h>
30#include <__type_traits/is_convertible.h>
31#include <__type_traits/is_implicitly_default_constructible.h>
32#include <__type_traits/is_nothrow_assignable.h>
33#include <__type_traits/is_nothrow_constructible.h>
34#include <__type_traits/is_relocatable.h>
35#include <__type_traits/is_swappable.h>
36#include <__type_traits/nat.h>
37#include <__type_traits/unwrap_ref.h>
38#include <__utility/declval.h>
39#include <__utility/forward.h>
40#include <__utility/integer_sequence.h>
41#include <__utility/move.h>
42#include <__utility/piecewise_construct.h>
43
44#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
45# pragma GCC system_header
46#endif
47
48_LIBCPP_PUSH_MACROS
49#include <__undef_macros>
50
51_LIBCPP_BEGIN_NAMESPACE_STD
52
53#ifndef _LIBCPP_CXX03_LANG
54
55template <class _T1, class _T2>
56struct __check_pair_construction {
57 template <int&...>
58 static constexpr bool __enable_implicit_default() {
59 return __is_implicitly_default_constructible<_T1>::value && __is_implicitly_default_constructible<_T2>::value;
60 }
61
62 template <int&...>
63 static constexpr bool __enable_default() {
64 return is_default_constructible<_T1>::value && is_default_constructible<_T2>::value;
65 }
66
67 template <class _U1, class _U2>
68 static constexpr bool __is_pair_constructible() {
69 return is_constructible<_T1, _U1>::value && is_constructible<_T2, _U2>::value;
70 }
71
72 template <class _U1, class _U2>
73 static constexpr bool __is_implicit() {
74 return is_convertible<_U1, _T1>::value && is_convertible<_U2, _T2>::value;
75 }
76};
77
78#endif
79
80template <class, class>
81struct __non_trivially_copyable_base {
82 _LIBCPP_CONSTEXPR __non_trivially_copyable_base() _NOEXCEPT {}
83 _LIBCPP_CONSTEXPR_SINCE_CXX14 __non_trivially_copyable_base(__non_trivially_copyable_base const&) _NOEXCEPT {}
84};
85
86template <class _T1, class _T2>
87struct pair
88#if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR)
89 : private __non_trivially_copyable_base<_T1, _T2>
90#endif
91{
92 using first_type = _T1;
93 using second_type = _T2;
94
95 _T1 first;
96 _T2 second;
97
98 using __trivially_relocatable _LIBCPP_NODEBUG =
99 __conditional_t<__is_trivially_relocatable_v<_T1> && __is_trivially_relocatable_v<_T2>, pair, void>;
100
101 pair(pair const&) = default;
102 pair(pair&&) = default;
103
104#ifdef _LIBCPP_CXX03_LANG
105 pair() : first(), second() {}
106
107 pair(_T1 const& __t1, _T2 const& __t2) : first(__t1), second(__t2) {}
108
109 template <class _U1, class _U2>
110 pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) {}
111
112 pair& operator=(pair const& __p) {
113 first = __p.first;
114 second = __p.second;
115 return *this;
116 }
117
118 // Extension: This is provided in C++03 because it allows properly handling the
119 // assignment to a pair containing references, which would be a hard
120 // error otherwise.
121 template <
122 class _U1,
123 class _U2,
124 __enable_if_t<is_assignable<first_type&, _U1 const&>::value && is_assignable<second_type&, _U2 const&>::value,
125 int> = 0>
126 pair& operator=(pair<_U1, _U2> const& __p) {
127 first = __p.first;
128 second = __p.second;
129 return *this;
130 }
131#else
132 template <class _CheckArgsDep = __check_pair_construction<_T1, _T2>,
133 __enable_if_t<_CheckArgsDep::__enable_default(), int> = 0>
134 explicit(!_CheckArgsDep::__enable_implicit_default()) constexpr pair() noexcept(
135 is_nothrow_default_constructible<first_type>::value && is_nothrow_default_constructible<second_type>::value)
136 : first(), second() {}
137
138 template <class _CheckArgsDep = __check_pair_construction<_T1, _T2>,
139 __enable_if_t<_CheckArgsDep::template __is_pair_constructible<_T1 const&, _T2 const&>(), int> = 0>
140 _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_CheckArgsDep::template __is_implicit<_T1 const&, _T2 const&>())
141 pair(_T1 const& __t1, _T2 const& __t2) noexcept(is_nothrow_copy_constructible<first_type>::value &&
142 is_nothrow_copy_constructible<second_type>::value)
143 : first(__t1), second(__t2) {}
144
145 template <
146# if _LIBCPP_STD_VER >= 23 // http://wg21.link/P1951
147 class _U1 = _T1,
148 class _U2 = _T2,
149# else
150 class _U1,
151 class _U2,
152# endif
153 __enable_if_t<__check_pair_construction<_T1, _T2>::template __is_pair_constructible<_U1, _U2>(), int> = 0 >
154 _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1, _U2>())
155 pair(_U1&& __u1, _U2&& __u2) noexcept(is_nothrow_constructible<first_type, _U1>::value &&
156 is_nothrow_constructible<second_type, _U2>::value)
157 : first(std::forward<_U1>(__u1)), second(std::forward<_U2>(__u2)) {
158 }
159
160# if _LIBCPP_STD_VER >= 23
161 template <class _U1,
162 class _U2,
163 __enable_if_t<__check_pair_construction<_T1, _T2>::template __is_pair_constructible<_U1&, _U2&>(), int> = 0>
164 constexpr explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1&, _U2&>())
165 pair(pair<_U1, _U2>& __p) noexcept((is_nothrow_constructible<first_type, _U1&>::value &&
166 is_nothrow_constructible<second_type, _U2&>::value))
167 : first(__p.first), second(__p.second) {}
168# endif
169
170 template <
171 class _U1,
172 class _U2,
173 __enable_if_t<__check_pair_construction<_T1, _T2>::template __is_pair_constructible<_U1 const&, _U2 const&>(),
174 int> = 0>
175 _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(
176 !__check_pair_construction<_T1, _T2>::template __is_implicit<_U1 const&, _U2 const&>())
177 pair(pair<_U1, _U2> const& __p) noexcept(is_nothrow_constructible<first_type, _U1 const&>::value &&
178 is_nothrow_constructible<second_type, _U2 const&>::value)
179 : first(__p.first), second(__p.second) {}
180
181 template <class _U1,
182 class _U2,
183 __enable_if_t<__check_pair_construction<_T1, _T2>::template __is_pair_constructible<_U1, _U2>(), int> = 0>
184 _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<_U1, _U2>())
185 pair(pair<_U1, _U2>&& __p) noexcept(is_nothrow_constructible<first_type, _U1&&>::value &&
186 is_nothrow_constructible<second_type, _U2&&>::value)
187 : first(std::forward<_U1>(__p.first)), second(std::forward<_U2>(__p.second)) {}
188
189# if _LIBCPP_STD_VER >= 23
190 template <
191 class _U1,
192 class _U2,
193 __enable_if_t<__check_pair_construction<_T1, _T2>::template __is_pair_constructible<const _U1&&, const _U2&&>(),
194 int> = 0>
195 constexpr explicit(!__check_pair_construction<_T1, _T2>::template __is_implicit<const _U1&&, const _U2&&>())
196 pair(const pair<_U1, _U2>&& __p) noexcept(is_nothrow_constructible<first_type, const _U1&&>::value &&
197 is_nothrow_constructible<second_type, const _U2&&>::value)
198 : first(std::move(__p.first)), second(std::move(__p.second)) {}
199# endif
200
201# if _LIBCPP_STD_VER >= 23
202 template <__pair_like_no_subrange _PairLike>
203 requires(is_constructible_v<first_type, decltype(std::get<0>(std::declval<_PairLike &&>()))> &&
204 is_constructible_v<second_type, decltype(std::get<1>(std::declval<_PairLike &&>()))>)
205 constexpr explicit(!is_convertible_v<decltype(std::get<0>(std::declval<_PairLike&&>())), first_type> ||
206 !is_convertible_v<decltype(std::get<1>(std::declval<_PairLike&&>())), second_type>)
207 pair(_PairLike&& __p)
208 : first(std::get<0>(std::forward<_PairLike>(__p))), second(std::get<1>(std::forward<_PairLike>(__p))) {}
209# endif
210
211 template <class... _Args1, class... _Args2>
212 _LIBCPP_CONSTEXPR_SINCE_CXX20
213 pair(piecewise_construct_t __pc, tuple<_Args1...> __first_args, tuple<_Args2...> __second_args) noexcept(
214 is_nothrow_constructible<first_type, _Args1...>::value && is_nothrow_constructible<second_type, _Args2...>::value)
215 : pair(__pc, __first_args, __second_args, __index_sequence_for<_Args1...>(), __index_sequence_for<_Args2...>()) {}
216
217 _LIBCPP_CONSTEXPR_SINCE_CXX20 pair&
218 operator=(__conditional_t<is_copy_assignable<first_type>::value && is_copy_assignable<second_type>::value,
219 pair,
220 __nat> const& __p) noexcept(is_nothrow_copy_assignable<first_type>::value &&
221 is_nothrow_copy_assignable<second_type>::value) {
222 first = __p.first;
223 second = __p.second;
224 return *this;
225 }
226
227 _LIBCPP_CONSTEXPR_SINCE_CXX20 pair& operator=(
228 __conditional_t<is_move_assignable<first_type>::value && is_move_assignable<second_type>::value, pair, __nat>&&
229 __p) noexcept(is_nothrow_move_assignable<first_type>::value &&
230 is_nothrow_move_assignable<second_type>::value) {
231 first = std::forward<first_type>(__p.first);
232 second = std::forward<second_type>(__p.second);
233 return *this;
234 }
235
236 template <
237 class _U1,
238 class _U2,
239 __enable_if_t<is_assignable<first_type&, _U1 const&>::value && is_assignable<second_type&, _U2 const&>::value,
240 int> = 0>
241 _LIBCPP_CONSTEXPR_SINCE_CXX20 pair& operator=(pair<_U1, _U2> const& __p) {
242 first = __p.first;
243 second = __p.second;
244 return *this;
245 }
246
247 template <class _U1,
248 class _U2,
249 __enable_if_t<is_assignable<first_type&, _U1>::value && is_assignable<second_type&, _U2>::value, int> = 0>
250 _LIBCPP_CONSTEXPR_SINCE_CXX20 pair& operator=(pair<_U1, _U2>&& __p) {
251 first = std::forward<_U1>(__p.first);
252 second = std::forward<_U2>(__p.second);
253 return *this;
254 }
255
256# if _LIBCPP_STD_VER >= 23
257 template <class = void>
258 constexpr const pair& operator=(pair const& __p) const
259 noexcept(is_nothrow_copy_assignable_v<const first_type> && is_nothrow_copy_assignable_v<const second_type>)
260 requires(is_copy_assignable_v<const first_type> && is_copy_assignable_v<const second_type>)
261 {
262 first = __p.first;
263 second = __p.second;
264 return *this;
265 }
266
267 template <class = void>
268 constexpr const pair& operator=(pair&& __p) const
269 noexcept(is_nothrow_assignable_v<const first_type&, first_type> &&
270 is_nothrow_assignable_v<const second_type&, second_type>)
271 requires(is_assignable_v<const first_type&, first_type> && is_assignable_v<const second_type&, second_type>)
272 {
273 first = std::forward<first_type>(__p.first);
274 second = std::forward<second_type>(__p.second);
275 return *this;
276 }
277
278 template <class _U1, class _U2>
279 constexpr const pair& operator=(const pair<_U1, _U2>& __p) const
280 requires(is_assignable_v<const first_type&, const _U1&> && is_assignable_v<const second_type&, const _U2&>)
281 {
282 first = __p.first;
283 second = __p.second;
284 return *this;
285 }
286
287 template <class _U1, class _U2>
288 constexpr const pair& operator=(pair<_U1, _U2>&& __p) const
289 requires(is_assignable_v<const first_type&, _U1> && is_assignable_v<const second_type&, _U2>)
290 {
291 first = std::forward<_U1>(__p.first);
292 second = std::forward<_U2>(__p.second);
293 return *this;
294 }
295
296 template <__pair_like_no_subrange _PairLike>
297 requires(__different_from<_PairLike, pair> &&
298 is_assignable_v<first_type&, decltype(std::get<0>(std::declval<_PairLike>()))> &&
299 is_assignable_v<second_type&, decltype(std::get<1>(std::declval<_PairLike>()))>)
300 constexpr pair& operator=(_PairLike&& __p) {
301 first = std::get<0>(std::forward<_PairLike>(__p));
302 second = std::get<1>(std::forward<_PairLike>(__p));
303 return *this;
304 }
305
306 template <__pair_like_no_subrange _PairLike>
307 requires(__different_from<_PairLike, pair> &&
308 is_assignable_v<first_type const&, decltype(std::get<0>(std::declval<_PairLike>()))> &&
309 is_assignable_v<second_type const&, decltype(std::get<1>(std::declval<_PairLike>()))>)
310 constexpr pair const& operator=(_PairLike&& __p) const {
311 first = std::get<0>(std::forward<_PairLike>(__p));
312 second = std::get<1>(std::forward<_PairLike>(__p));
313 return *this;
314 }
315# endif // _LIBCPP_STD_VER >= 23
316
317 // Prior to C++23, we provide an approximation of constructors and assignment operators from
318 // pair-like types. This was historically provided as an extension.
319# if _LIBCPP_STD_VER < 23
320 // from std::tuple
321 template <class _U1,
322 class _U2,
323 __enable_if_t<is_convertible<_U1 const&, _T1>::value && is_convertible<_U2 const&, _T2>::value, int> = 0>
324 _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(tuple<_U1, _U2> const& __p) : first(std::get<0>(__p)), second(std::get<1>(__p)) {}
325
326 template < class _U1,
327 class _U2,
328 __enable_if_t<is_constructible<_T1, _U1 const&>::value && is_constructible<_T2, _U2 const&>::value &&
329 !(is_convertible<_U1 const&, _T1>::value && is_convertible<_U2 const&, _T2>::value),
330 int> = 0>
331 _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(tuple<_U1, _U2> const& __p)
332 : first(std::get<0>(__p)), second(std::get<1>(__p)) {}
333
334 template <class _U1,
335 class _U2,
336 __enable_if_t<is_convertible<_U1, _T1>::value && is_convertible<_U2, _T2>::value, int> = 0>
337 _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(tuple<_U1, _U2>&& __p)
338 : first(std::get<0>(std::move(__p))), second(std::get<1>(std::move(__p))) {}
339
340 template <class _U1,
341 class _U2,
342 __enable_if_t<is_constructible<_T1, _U1>::value && is_constructible<_T2, _U2>::value &&
343 !(is_convertible<_U1, _T1>::value && is_convertible<_U2, _T2>::value) > = 0>
344 _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(tuple<_U1, _U2>&& __p)
345 : first(std::get<0>(std::move(__p))), second(std::get<1>(std::move(__p))) {}
346
347 template <class _U1,
348 class _U2,
349 __enable_if_t<is_assignable<_T1&, _U1 const&>::value && is_assignable<_T2&, _U2 const&>::value, int> = 0>
350 _LIBCPP_CONSTEXPR_SINCE_CXX14 pair& operator=(tuple<_U1, _U2> const& __p) {
351 first = std::get<0>(__p);
352 second = std::get<1>(__p);
353 return *this;
354 }
355
356 template <class _U1,
357 class _U2,
358 __enable_if_t<is_assignable<_T1&, _U1&&>::value && is_assignable<_T2&, _U2&&>::value, int> = 0>
359 _LIBCPP_CONSTEXPR_SINCE_CXX14 pair& operator=(tuple<_U1, _U2>&& __p) {
360 first = std::get<0>(std::move(__p));
361 second = std::get<1>(std::move(__p));
362 return *this;
363 }
364
365 // from std::array
366 template <class _Up,
367 __enable_if_t<is_convertible<_Up const&, _T1>::value && is_convertible<_Up const&, _T2>::value, int> = 0>
368 _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(array<_Up, 2> const& __p) : first(__p[0]), second(__p[1]) {}
369
370 template <class _Up,
371 __enable_if_t<is_constructible<_T1, _Up const&>::value && is_constructible<_T2, _Up const&>::value &&
372 !(is_convertible<_Up const&, _T1>::value && is_convertible<_Up const&, _T2>::value),
373 int> = 0>
374 _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(array<_Up, 2> const& __p) : first(__p[0]), second(__p[1]) {}
375
376 template <class _Up, __enable_if_t< is_convertible<_Up, _T1>::value && is_convertible<_Up, _T2>::value, int> = 0>
377 _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(array<_Up, 2>&& __p) : first(std::move(__p)[0]), second(std::move(__p)[1]) {}
378
379 template <class _Up,
380 __enable_if_t<is_constructible<_T1, _Up>::value && is_constructible<_T2, _Up>::value &&
381 !(is_convertible<_Up, _T1>::value && is_convertible<_Up, _T2>::value),
382 int> = 0>
383 _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(array<_Up, 2>&& __p)
384 : first(std::move(__p)[0]), second(std::move(__p)[1]) {}
385
386 template <class _Up,
387 __enable_if_t<is_assignable<_T1&, _Up const&>::value && is_assignable<_T2&, _Up const&>::value, int> = 0>
388 _LIBCPP_CONSTEXPR_SINCE_CXX14 pair& operator=(array<_Up, 2> const& __p) {
389 first = std::get<0>(__p);
390 second = std::get<1>(__p);
391 return *this;
392 }
393
394 template <class _Up, __enable_if_t<is_assignable<_T1&, _Up>::value && is_assignable<_T2&, _Up>::value, int> = 0>
395 _LIBCPP_CONSTEXPR_SINCE_CXX14 pair& operator=(array<_Up, 2>&& __p) {
396 first = std::get<0>(std::move(__p));
397 second = std::get<1>(std::move(__p));
398 return *this;
399 }
400# endif // _LIBCPP_STD_VER < 23
401#endif // _LIBCPP_CXX03_LANG
402
403 _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(pair& __p)
404 _NOEXCEPT_(__is_nothrow_swappable_v<first_type>&& __is_nothrow_swappable_v<second_type>) {
405 using std::swap;
406 swap(first, __p.first);
407 swap(second, __p.second);
408 }
409
410#if _LIBCPP_STD_VER >= 23
411 constexpr void swap(const pair& __p) const
412 noexcept(__is_nothrow_swappable_v<const first_type> && __is_nothrow_swappable_v<const second_type>) {
413 using std::swap;
414 swap(first, __p.first);
415 swap(second, __p.second);
416 }
417#endif
418
419private:
420#ifndef _LIBCPP_CXX03_LANG
421 template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2>
422 _LIBCPP_CONSTEXPR_SINCE_CXX20
423 pair(piecewise_construct_t,
424 tuple<_Args1...>& __first_args,
425 tuple<_Args2...>& __second_args,
426 __index_sequence<_I1...>,
427 __index_sequence<_I2...>)
428 : first(std::forward<_Args1>(std::get<_I1>(__first_args))...),
429 second(std::forward<_Args2>(std::get<_I2>(__second_args))...) {}
430#endif
431};
432
433#if _LIBCPP_STD_VER >= 17
434template <class _T1, class _T2>
435pair(_T1, _T2) -> pair<_T1, _T2>;
436#endif
437
438// [pairs.spec], specialized algorithms
439
440template <class _T1, class _T2, class _U1, class _U2>
441inline _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator==(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y)
442#if _LIBCPP_STD_VER >= 26
443 requires requires {
444 { __x.first == __y.first } -> __boolean_testable;
445 { __x.second == __y.second } -> __boolean_testable;
446 }
447#endif
448{
449 return __x.first == __y.first && __x.second == __y.second;
450}
451
452#if _LIBCPP_STD_VER >= 20
453
454template <class _T1, class _T2, class _U1, class _U2>
455constexpr common_comparison_category_t< __synth_three_way_result<_T1, _U1>, __synth_three_way_result<_T2, _U2> >
456operator<=>(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
457 if (auto __c = std::__synth_three_way(__x.first, __y.first); __c != 0) {
458 return __c;
459 }
460 return std::__synth_three_way(__x.second, __y.second);
461}
462
463#else // _LIBCPP_STD_VER >= 20
464
465template <class _T1, class _T2, class _U1, class _U2>
466inline _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator!=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
467 return !(__x == __y);
468}
469
470template <class _T1, class _T2, class _U1, class _U2>
471inline _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator<(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
472 return __x.first < __y.first || (!(__y.first < __x.first) && __x.second < __y.second);
473}
474
475template <class _T1, class _T2, class _U1, class _U2>
476inline _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator>(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
477 return __y < __x;
478}
479
480template <class _T1, class _T2, class _U1, class _U2>
481inline _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator>=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
482 return !(__x < __y);
483}
484
485template <class _T1, class _T2, class _U1, class _U2>
486inline _LIBCPP_CONSTEXPR_SINCE_CXX14 bool operator<=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
487 return !(__y < __x);
488}
489
490#endif // _LIBCPP_STD_VER >= 20
491
492#if _LIBCPP_STD_VER >= 23
493template <class _T1, class _T2, class _U1, class _U2, template <class> class _TQual, template <class> class _UQual>
494 requires requires {
495 typename pair<common_reference_t<_TQual<_T1>, _UQual<_U1>>, common_reference_t<_TQual<_T2>, _UQual<_U2>>>;
496 }
497struct basic_common_reference<pair<_T1, _T2>, pair<_U1, _U2>, _TQual, _UQual> {
498 using type _LIBCPP_NODEBUG =
499 pair<common_reference_t<_TQual<_T1>, _UQual<_U1>>, common_reference_t<_TQual<_T2>, _UQual<_U2>>>;
500};
501
502template <class _T1, class _T2, class _U1, class _U2>
503 requires requires { typename pair<common_type_t<_T1, _U1>, common_type_t<_T2, _U2>>; }
504struct common_type<pair<_T1, _T2>, pair<_U1, _U2>> {
505 using type _LIBCPP_NODEBUG = pair<common_type_t<_T1, _U1>, common_type_t<_T2, _U2>>;
506};
507#endif // _LIBCPP_STD_VER >= 23
508
509template <class _T1, class _T2, __enable_if_t<__is_swappable_v<_T1> && __is_swappable_v<_T2>, int> = 0>
510inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y)
511 _NOEXCEPT_(__is_nothrow_swappable_v<_T1>&& __is_nothrow_swappable_v<_T2>) {
512 __x.swap(__y);
513}
514
515#if _LIBCPP_STD_VER >= 23
516template <class _T1, class _T2>
517 requires(__is_swappable_v<const _T1> && __is_swappable_v<const _T2>)
518constexpr void swap(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) noexcept(noexcept(__x.swap(__y))) {
519 __x.swap(__y);
520}
521#endif
522
523template <class _T1, class _T2>
524[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<__unwrap_ref_decay_t<_T1>, __unwrap_ref_decay_t<_T2> >
525make_pair(_T1&& __t1, _T2&& __t2) {
526 return pair<__unwrap_ref_decay_t<_T1>, __unwrap_ref_decay_t<_T2> >(std::forward<_T1>(__t1), std::forward<_T2>(__t2));
527}
528
529template <class _T1, class _T2>
530struct tuple_size<pair<_T1, _T2> > : public integral_constant<size_t, 2> {};
531
532template <size_t _Ip, class _T1, class _T2>
533struct tuple_element<_Ip, pair<_T1, _T2> > {
534 static_assert(_Ip < 2, "Index out of bounds in std::tuple_element<std::pair<T1, T2>>");
535};
536
537template <class _T1, class _T2>
538struct tuple_element<0, pair<_T1, _T2> > {
539 using type _LIBCPP_NODEBUG = _T1;
540};
541
542template <class _T1, class _T2>
543struct tuple_element<1, pair<_T1, _T2> > {
544 using type _LIBCPP_NODEBUG = _T2;
545};
546
547template <size_t _Ip>
548struct __get_pair;
549
550template <>
551struct __get_pair<0> {
552 template <class _T1, class _T2>
553 static _LIBCPP_CONSTEXPR_SINCE_CXX14 _T1& get(pair<_T1, _T2>& __p) _NOEXCEPT {
554 return __p.first;
555 }
556
557 template <class _T1, class _T2>
558 static _LIBCPP_CONSTEXPR_SINCE_CXX14 const _T1& get(const pair<_T1, _T2>& __p) _NOEXCEPT {
559 return __p.first;
560 }
561
562 template <class _T1, class _T2>
563 static _LIBCPP_CONSTEXPR_SINCE_CXX14 _T1&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {
564 return std::forward<_T1>(__p.first);
565 }
566
567 template <class _T1, class _T2>
568 static _LIBCPP_CONSTEXPR_SINCE_CXX14 const _T1&& get(const pair<_T1, _T2>&& __p) _NOEXCEPT {
569 return std::forward<const _T1>(__p.first);
570 }
571};
572
573template <>
574struct __get_pair<1> {
575 template <class _T1, class _T2>
576 static _LIBCPP_CONSTEXPR_SINCE_CXX14 _T2& get(pair<_T1, _T2>& __p) _NOEXCEPT {
577 return __p.second;
578 }
579
580 template <class _T1, class _T2>
581 static _LIBCPP_CONSTEXPR_SINCE_CXX14 const _T2& get(const pair<_T1, _T2>& __p) _NOEXCEPT {
582 return __p.second;
583 }
584
585 template <class _T1, class _T2>
586 static _LIBCPP_CONSTEXPR_SINCE_CXX14 _T2&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {
587 return std::forward<_T2>(__p.second);
588 }
589
590 template <class _T1, class _T2>
591 static _LIBCPP_CONSTEXPR_SINCE_CXX14 const _T2&& get(const pair<_T1, _T2>&& __p) _NOEXCEPT {
592 return std::forward<const _T2>(__p.second);
593 }
594};
595
596template <size_t _Ip, class _T1, class _T2>
597[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Ip, pair<_T1, _T2> >::type&
598get(pair<_T1, _T2>& __p) _NOEXCEPT {
599 return __get_pair<_Ip>::get(__p);
600}
601
602template <size_t _Ip, class _T1, class _T2>
603[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Ip, pair<_T1, _T2> >::type&
604get(const pair<_T1, _T2>& __p) _NOEXCEPT {
605 return __get_pair<_Ip>::get(__p);
606}
607
608template <size_t _Ip, class _T1, class _T2>
609[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Ip, pair<_T1, _T2> >::type&&
610get(pair<_T1, _T2>&& __p) _NOEXCEPT {
611 return __get_pair<_Ip>::get(std::move(__p));
612}
613
614template <size_t _Ip, class _T1, class _T2>
615[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Ip, pair<_T1, _T2> >::type&&
616get(const pair<_T1, _T2>&& __p) _NOEXCEPT {
617 return __get_pair<_Ip>::get(std::move(__p));
618}
619
620#if _LIBCPP_STD_VER >= 14
621template <class _T1, class _T2>
622[[__nodiscard__]] inline constexpr _T1& get(pair<_T1, _T2>& __p) _NOEXCEPT {
623 return __p.first;
624}
625
626template <class _T1, class _T2>
627[[__nodiscard__]] inline constexpr _T1 const& get(pair<_T1, _T2> const& __p) _NOEXCEPT {
628 return __p.first;
629}
630
631template <class _T1, class _T2>
632[[__nodiscard__]] inline constexpr _T1&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {
633 return std::forward<_T1&&>(__p.first);
634}
635
636template <class _T1, class _T2>
637[[__nodiscard__]] inline constexpr _T1 const&& get(pair<_T1, _T2> const&& __p) _NOEXCEPT {
638 return std::forward<_T1 const&&>(__p.first);
639}
640
641template <class _T2, class _T1>
642[[__nodiscard__]] inline constexpr _T2& get(pair<_T1, _T2>& __p) _NOEXCEPT {
643 return __p.second;
644}
645
646template <class _T2, class _T1>
647[[__nodiscard__]] inline constexpr _T2 const& get(pair<_T1, _T2> const& __p) _NOEXCEPT {
648 return __p.second;
649}
650
651template <class _T2, class _T1>
652[[__nodiscard__]] inline constexpr _T2&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {
653 return std::forward<_T2&&>(__p.second);
654}
655
656template <class _T2, class _T1>
657[[__nodiscard__]] inline constexpr _T2 const&& get(pair<_T1, _T2> const&& __p) _NOEXCEPT {
658 return std::forward<_T2 const&&>(__p.second);
659}
660
661#endif // _LIBCPP_STD_VER >= 14
662
663_LIBCPP_END_NAMESPACE_STD
664
665_LIBCPP_POP_MACROS
666
667#endif // _LIBCPP___UTILITY_PAIR_H
668