xref: /freebsd-src/contrib/llvm-project/libcxx/include/__utility/pair.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric 
9fe6060f1SDimitry Andric #ifndef _LIBCPP___UTILITY_PAIR_H
10fe6060f1SDimitry Andric #define _LIBCPP___UTILITY_PAIR_H
11fe6060f1SDimitry Andric 
12349cc55cSDimitry Andric #include <__compare/common_comparison_category.h>
13349cc55cSDimitry Andric #include <__compare/synth_three_way.h>
1406c3fb27SDimitry Andric #include <__concepts/different_from.h>
15fe6060f1SDimitry Andric #include <__config>
1606c3fb27SDimitry Andric #include <__fwd/array.h>
1706c3fb27SDimitry Andric #include <__fwd/pair.h>
18bdd1243dSDimitry Andric #include <__fwd/tuple.h>
1906c3fb27SDimitry Andric #include <__tuple/sfinae_helpers.h>
2006c3fb27SDimitry Andric #include <__tuple/tuple_element.h>
2106c3fb27SDimitry Andric #include <__tuple/tuple_indices.h>
22*0fca6ea1SDimitry Andric #include <__tuple/tuple_like_no_subrange.h>
2306c3fb27SDimitry Andric #include <__tuple/tuple_size.h>
24bdd1243dSDimitry Andric #include <__type_traits/common_reference.h>
25bdd1243dSDimitry Andric #include <__type_traits/common_type.h>
26bdd1243dSDimitry Andric #include <__type_traits/conditional.h>
2706c3fb27SDimitry Andric #include <__type_traits/decay.h>
2806c3fb27SDimitry Andric #include <__type_traits/integral_constant.h>
29bdd1243dSDimitry Andric #include <__type_traits/is_assignable.h>
30bdd1243dSDimitry Andric #include <__type_traits/is_constructible.h>
31bdd1243dSDimitry Andric #include <__type_traits/is_convertible.h>
32bdd1243dSDimitry Andric #include <__type_traits/is_implicitly_default_constructible.h>
33bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_assignable.h>
34bdd1243dSDimitry Andric #include <__type_traits/is_nothrow_constructible.h>
35*0fca6ea1SDimitry Andric #include <__type_traits/is_reference.h>
36bdd1243dSDimitry Andric #include <__type_traits/is_same.h>
37bdd1243dSDimitry Andric #include <__type_traits/is_swappable.h>
38*0fca6ea1SDimitry Andric #include <__type_traits/is_trivially_relocatable.h>
39bdd1243dSDimitry Andric #include <__type_traits/nat.h>
4006c3fb27SDimitry Andric #include <__type_traits/remove_cvref.h>
4106c3fb27SDimitry Andric #include <__type_traits/unwrap_ref.h>
4206c3fb27SDimitry Andric #include <__utility/declval.h>
43fe6060f1SDimitry Andric #include <__utility/forward.h>
44fe6060f1SDimitry Andric #include <__utility/move.h>
45fe6060f1SDimitry Andric #include <__utility/piecewise_construct.h>
46fe6060f1SDimitry Andric #include <cstddef>
47fe6060f1SDimitry Andric 
48fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
49fe6060f1SDimitry Andric #  pragma GCC system_header
50fe6060f1SDimitry Andric #endif
51fe6060f1SDimitry Andric 
5206c3fb27SDimitry Andric _LIBCPP_PUSH_MACROS
5306c3fb27SDimitry Andric #include <__undef_macros>
5406c3fb27SDimitry Andric 
55fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
56fe6060f1SDimitry Andric 
57fe6060f1SDimitry Andric template <class, class>
58fe6060f1SDimitry Andric struct __non_trivially_copyable_base {
59cb14a3feSDimitry Andric   _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI __non_trivially_copyable_base() _NOEXCEPT {}
6006c3fb27SDimitry Andric   _LIBCPP_CONSTEXPR_SINCE_CXX14 _LIBCPP_HIDE_FROM_ABI
61fe6060f1SDimitry Andric   __non_trivially_copyable_base(__non_trivially_copyable_base const&) _NOEXCEPT {}
62fe6060f1SDimitry Andric };
6306c3fb27SDimitry Andric 
64fe6060f1SDimitry Andric template <class _T1, class _T2>
65fe6060f1SDimitry Andric struct _LIBCPP_TEMPLATE_VIS pair
66fe6060f1SDimitry Andric #if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR)
67fe6060f1SDimitry Andric     : private __non_trivially_copyable_base<_T1, _T2>
68fe6060f1SDimitry Andric #endif
69fe6060f1SDimitry Andric {
7006c3fb27SDimitry Andric   using first_type  = _T1;
7106c3fb27SDimitry Andric   using second_type = _T2;
72fe6060f1SDimitry Andric 
73fe6060f1SDimitry Andric   _T1 first;
74fe6060f1SDimitry Andric   _T2 second;
75fe6060f1SDimitry Andric 
76*0fca6ea1SDimitry Andric   using __trivially_relocatable =
77*0fca6ea1SDimitry Andric       __conditional_t<__libcpp_is_trivially_relocatable<_T1>::value && __libcpp_is_trivially_relocatable<_T2>::value,
78*0fca6ea1SDimitry Andric                       pair,
79*0fca6ea1SDimitry Andric                       void>;
80*0fca6ea1SDimitry Andric 
8106c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair(pair const&) = default;
8206c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair(pair&&)      = default;
83fe6060f1SDimitry Andric 
84*0fca6ea1SDimitry Andric   // When we are requested for pair to be trivially copyable by the ABI macro, we use defaulted members
85*0fca6ea1SDimitry Andric   // if it is both legal to do it (i.e. no references) and we have a way to actually implement it, which requires
86*0fca6ea1SDimitry Andric   // the __enable_if__ attribute before C++20.
87*0fca6ea1SDimitry Andric #ifdef _LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR
88*0fca6ea1SDimitry Andric   // FIXME: This should really just be a static constexpr variable. It's in a struct to avoid gdb printing the value
89*0fca6ea1SDimitry Andric   // when printing a pair
90*0fca6ea1SDimitry Andric   struct __has_defaulted_members {
91*0fca6ea1SDimitry Andric     static const bool value = !is_reference<first_type>::value && !is_reference<second_type>::value;
92*0fca6ea1SDimitry Andric   };
93*0fca6ea1SDimitry Andric #  if _LIBCPP_STD_VER >= 20
94*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr pair& operator=(const pair&)
95*0fca6ea1SDimitry Andric     requires __has_defaulted_members::value
96*0fca6ea1SDimitry Andric   = default;
97*0fca6ea1SDimitry Andric 
98*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr pair& operator=(pair&&)
99*0fca6ea1SDimitry Andric     requires __has_defaulted_members::value
100*0fca6ea1SDimitry Andric   = default;
101*0fca6ea1SDimitry Andric #  elif __has_attribute(__enable_if__)
102*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair& operator=(const pair&)
103*0fca6ea1SDimitry Andric       __attribute__((__enable_if__(__has_defaulted_members::value, ""))) = default;
104*0fca6ea1SDimitry Andric 
105*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair& operator=(pair&&)
106*0fca6ea1SDimitry Andric       __attribute__((__enable_if__(__has_defaulted_members::value, ""))) = default;
107*0fca6ea1SDimitry Andric #  else
108*0fca6ea1SDimitry Andric #    error "_LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR isn't supported with this compiler"
109*0fca6ea1SDimitry Andric #  endif
110*0fca6ea1SDimitry Andric #else
111*0fca6ea1SDimitry Andric   struct __has_defaulted_members {
112*0fca6ea1SDimitry Andric     static const bool value = false;
113*0fca6ea1SDimitry Andric   };
114*0fca6ea1SDimitry Andric #endif // defined(_LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR) && __has_attribute(__enable_if__)
115*0fca6ea1SDimitry Andric 
116fe6060f1SDimitry Andric #ifdef _LIBCPP_CXX03_LANG
117cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair() : first(), second() {}
118fe6060f1SDimitry Andric 
119cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair(_T1 const& __t1, _T2 const& __t2) : first(__t1), second(__t2) {}
120fe6060f1SDimitry Andric 
121fe6060f1SDimitry Andric   template <class _U1, class _U2>
122cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) {}
123fe6060f1SDimitry Andric 
124cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair& operator=(pair const& __p) {
125fe6060f1SDimitry Andric     first  = __p.first;
126fe6060f1SDimitry Andric     second = __p.second;
127fe6060f1SDimitry Andric     return *this;
128fe6060f1SDimitry Andric   }
12906c3fb27SDimitry Andric 
13006c3fb27SDimitry Andric   // Extension: This is provided in C++03 because it allows properly handling the
13106c3fb27SDimitry Andric   //            assignment to a pair containing references, which would be a hard
13206c3fb27SDimitry Andric   //            error otherwise.
133*0fca6ea1SDimitry Andric   template <
134*0fca6ea1SDimitry Andric       class _U1,
135cb14a3feSDimitry Andric       class _U2,
136*0fca6ea1SDimitry Andric       __enable_if_t<is_assignable<first_type&, _U1 const&>::value && is_assignable<second_type&, _U2 const&>::value,
137*0fca6ea1SDimitry Andric                     int> = 0>
138cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair& operator=(pair<_U1, _U2> const& __p) {
13906c3fb27SDimitry Andric     first  = __p.first;
14006c3fb27SDimitry Andric     second = __p.second;
14106c3fb27SDimitry Andric     return *this;
14206c3fb27SDimitry Andric   }
143fe6060f1SDimitry Andric #else
144fe6060f1SDimitry Andric   struct _CheckArgs {
145fe6060f1SDimitry Andric     template <int&...>
146*0fca6ea1SDimitry Andric     static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_implicit_default() {
147*0fca6ea1SDimitry Andric       return __is_implicitly_default_constructible<_T1>::value && __is_implicitly_default_constructible<_T2>::value;
148fe6060f1SDimitry Andric     }
149fe6060f1SDimitry Andric 
150fe6060f1SDimitry Andric     template <int&...>
151*0fca6ea1SDimitry Andric     static _LIBCPP_HIDE_FROM_ABI constexpr bool __enable_default() {
152*0fca6ea1SDimitry Andric       return is_default_constructible<_T1>::value && is_default_constructible<_T2>::value;
153fe6060f1SDimitry Andric     }
154fe6060f1SDimitry Andric 
155fe6060f1SDimitry Andric     template <class _U1, class _U2>
15606c3fb27SDimitry Andric     static _LIBCPP_HIDE_FROM_ABI constexpr bool __is_pair_constructible() {
157cb14a3feSDimitry Andric       return is_constructible<first_type, _U1>::value && is_constructible<second_type, _U2>::value;
158bdd1243dSDimitry Andric     }
159bdd1243dSDimitry Andric 
160bdd1243dSDimitry Andric     template <class _U1, class _U2>
16106c3fb27SDimitry Andric     static _LIBCPP_HIDE_FROM_ABI constexpr bool __is_implicit() {
162cb14a3feSDimitry Andric       return is_convertible<_U1, first_type>::value && is_convertible<_U2, second_type>::value;
163bdd1243dSDimitry Andric     }
164fe6060f1SDimitry Andric   };
165fe6060f1SDimitry Andric 
166fe6060f1SDimitry Andric   template <bool _MaybeEnable>
167cb14a3feSDimitry Andric   using _CheckArgsDep _LIBCPP_NODEBUG =
168cb14a3feSDimitry Andric       typename conditional< _MaybeEnable, _CheckArgs, __check_tuple_constructor_fail>::type;
169fe6060f1SDimitry Andric 
170*0fca6ea1SDimitry Andric   template <bool _Dummy = true, __enable_if_t<_CheckArgsDep<_Dummy>::__enable_default(), int> = 0>
171*0fca6ea1SDimitry Andric   explicit(!_CheckArgsDep<_Dummy>::__enable_implicit_default()) _LIBCPP_HIDE_FROM_ABI constexpr pair() noexcept(
172cb14a3feSDimitry Andric       is_nothrow_default_constructible<first_type>::value && is_nothrow_default_constructible<second_type>::value)
173fe6060f1SDimitry Andric       : first(), second() {}
174fe6060f1SDimitry Andric 
1755f757f3fSDimitry Andric   template <bool _Dummy = true,
176*0fca6ea1SDimitry Andric             __enable_if_t<_CheckArgsDep<_Dummy>::template __is_pair_constructible<_T1 const&, _T2 const&>(), int> = 0>
177*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
178*0fca6ea1SDimitry Andric   _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_CheckArgsDep<_Dummy>::template __is_implicit<_T1 const&, _T2 const&>())
179*0fca6ea1SDimitry Andric       pair(_T1 const& __t1, _T2 const& __t2) noexcept(is_nothrow_copy_constructible<first_type>::value &&
180*0fca6ea1SDimitry Andric                                                       is_nothrow_copy_constructible<second_type>::value)
181fe6060f1SDimitry Andric       : first(__t1), second(__t2) {}
182fe6060f1SDimitry Andric 
183349cc55cSDimitry Andric   template <
18406c3fb27SDimitry Andric #  if _LIBCPP_STD_VER >= 23 // http://wg21.link/P1951
185cb14a3feSDimitry Andric       class _U1 = _T1,
186cb14a3feSDimitry Andric       class _U2 = _T2,
187349cc55cSDimitry Andric #  else
188cb14a3feSDimitry Andric       class _U1,
189cb14a3feSDimitry Andric       class _U2,
190349cc55cSDimitry Andric #  endif
191*0fca6ea1SDimitry Andric       __enable_if_t<_CheckArgs::template __is_pair_constructible<_U1, _U2>(), int> = 0 >
192*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_CheckArgs::template __is_implicit<_U1, _U2>())
193*0fca6ea1SDimitry Andric       pair(_U1&& __u1, _U2&& __u2) noexcept(is_nothrow_constructible<first_type, _U1>::value &&
194*0fca6ea1SDimitry Andric                                             is_nothrow_constructible<second_type, _U2>::value)
195cb14a3feSDimitry Andric       : first(std::forward<_U1>(__u1)), second(std::forward<_U2>(__u2)) {
196cb14a3feSDimitry Andric   }
197fe6060f1SDimitry Andric 
19806c3fb27SDimitry Andric #  if _LIBCPP_STD_VER >= 23
199*0fca6ea1SDimitry Andric   template <class _U1, class _U2, __enable_if_t<_CheckArgs::template __is_pair_constructible<_U1&, _U2&>(), int> = 0>
200cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_CheckArgs::template __is_implicit<_U1&, _U2&>())
201cb14a3feSDimitry Andric       pair(pair<_U1, _U2>& __p) noexcept((is_nothrow_constructible<first_type, _U1&>::value &&
202bdd1243dSDimitry Andric                                           is_nothrow_constructible<second_type, _U2&>::value))
203bdd1243dSDimitry Andric       : first(__p.first), second(__p.second) {}
204bdd1243dSDimitry Andric #  endif
205bdd1243dSDimitry Andric 
206cb14a3feSDimitry Andric   template <class _U1,
207cb14a3feSDimitry Andric             class _U2,
208*0fca6ea1SDimitry Andric             __enable_if_t<_CheckArgs::template __is_pair_constructible<_U1 const&, _U2 const&>(), int> = 0>
209*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
210*0fca6ea1SDimitry Andric   _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_CheckArgs::template __is_implicit<_U1 const&, _U2 const&>())
211*0fca6ea1SDimitry Andric       pair(pair<_U1, _U2> const& __p) noexcept(is_nothrow_constructible<first_type, _U1 const&>::value &&
212*0fca6ea1SDimitry Andric                                                is_nothrow_constructible<second_type, _U2 const&>::value)
213fe6060f1SDimitry Andric       : first(__p.first), second(__p.second) {}
214fe6060f1SDimitry Andric 
215*0fca6ea1SDimitry Andric   template <class _U1, class _U2, __enable_if_t<_CheckArgs::template __is_pair_constructible<_U1, _U2>(), int> = 0>
216*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit(!_CheckArgs::template __is_implicit<_U1, _U2>())
217*0fca6ea1SDimitry Andric       pair(pair<_U1, _U2>&& __p) noexcept(is_nothrow_constructible<first_type, _U1&&>::value &&
218*0fca6ea1SDimitry Andric                                           is_nothrow_constructible<second_type, _U2&&>::value)
21906c3fb27SDimitry Andric       : first(std::forward<_U1>(__p.first)), second(std::forward<_U2>(__p.second)) {}
220fe6060f1SDimitry Andric 
22106c3fb27SDimitry Andric #  if _LIBCPP_STD_VER >= 23
222cb14a3feSDimitry Andric   template <class _U1,
223cb14a3feSDimitry Andric             class _U2,
224*0fca6ea1SDimitry Andric             __enable_if_t<_CheckArgs::template __is_pair_constructible<const _U1&&, const _U2&&>(), int> = 0>
225cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!_CheckArgs::template __is_implicit<const _U1&&, const _U2&&>())
226cb14a3feSDimitry Andric       pair(const pair<_U1, _U2>&& __p) noexcept(is_nothrow_constructible<first_type, const _U1&&>::value &&
227bdd1243dSDimitry Andric                                                 is_nothrow_constructible<second_type, const _U2&&>::value)
228bdd1243dSDimitry Andric       : first(std::move(__p.first)), second(std::move(__p.second)) {}
229bdd1243dSDimitry Andric #  endif
230bdd1243dSDimitry Andric 
23106c3fb27SDimitry Andric #  if _LIBCPP_STD_VER >= 23
232*0fca6ea1SDimitry Andric   // TODO: Remove this workaround in LLVM 20. The bug got fixed in Clang 18.
23306c3fb27SDimitry Andric   // This is a workaround for http://llvm.org/PR60710. We should be able to remove it once Clang is fixed.
2343bd749dbSDimitry Andric   template <class _PairLike>
23506c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI static constexpr bool __pair_like_explicit_wknd() {
236*0fca6ea1SDimitry Andric     if constexpr (__pair_like_no_subrange<_PairLike>) {
23706c3fb27SDimitry Andric       return !is_convertible_v<decltype(std::get<0>(std::declval<_PairLike&&>())), first_type> ||
23806c3fb27SDimitry Andric              !is_convertible_v<decltype(std::get<1>(std::declval<_PairLike&&>())), second_type>;
23906c3fb27SDimitry Andric     }
24006c3fb27SDimitry Andric     return false;
24106c3fb27SDimitry Andric   }
242fe6060f1SDimitry Andric 
243*0fca6ea1SDimitry Andric   template <__pair_like_no_subrange _PairLike>
244*0fca6ea1SDimitry Andric     requires(is_constructible_v<first_type, decltype(std::get<0>(std::declval<_PairLike &&>()))> &&
24506c3fb27SDimitry Andric              is_constructible_v<second_type, decltype(std::get<1>(std::declval<_PairLike &&>()))>)
246cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit(__pair_like_explicit_wknd<_PairLike>()) pair(_PairLike&& __p)
24706c3fb27SDimitry Andric       : first(std::get<0>(std::forward<_PairLike>(__p))), second(std::get<1>(std::forward<_PairLike>(__p))) {}
24806c3fb27SDimitry Andric #  endif
249fe6060f1SDimitry Andric 
250fe6060f1SDimitry Andric   template <class... _Args1, class... _Args2>
25106c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
252*0fca6ea1SDimitry Andric   pair(piecewise_construct_t __pc, tuple<_Args1...> __first_args, tuple<_Args2...> __second_args) noexcept(
253*0fca6ea1SDimitry Andric       is_nothrow_constructible<first_type, _Args1...>::value && is_nothrow_constructible<second_type, _Args2...>::value)
254cb14a3feSDimitry Andric       : pair(__pc,
255cb14a3feSDimitry Andric              __first_args,
256cb14a3feSDimitry Andric              __second_args,
257fe6060f1SDimitry Andric              typename __make_tuple_indices<sizeof...(_Args1)>::type(),
258fe6060f1SDimitry Andric              typename __make_tuple_indices<sizeof...(_Args2) >::type()) {}
259fe6060f1SDimitry Andric 
260cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair&
261*0fca6ea1SDimitry Andric   operator=(__conditional_t<!__has_defaulted_members::value && is_copy_assignable<first_type>::value &&
262*0fca6ea1SDimitry Andric                                 is_copy_assignable<second_type>::value,
263cb14a3feSDimitry Andric                             pair,
264*0fca6ea1SDimitry Andric                             __nat> const& __p) noexcept(is_nothrow_copy_assignable<first_type>::value &&
265*0fca6ea1SDimitry Andric                                                         is_nothrow_copy_assignable<second_type>::value) {
266fe6060f1SDimitry Andric     first  = __p.first;
267fe6060f1SDimitry Andric     second = __p.second;
268fe6060f1SDimitry Andric     return *this;
269fe6060f1SDimitry Andric   }
270fe6060f1SDimitry Andric 
271*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair&
272*0fca6ea1SDimitry Andric   operator=(__conditional_t<!__has_defaulted_members::value && is_move_assignable<first_type>::value &&
273*0fca6ea1SDimitry Andric                                 is_move_assignable<second_type>::value,
274*0fca6ea1SDimitry Andric                             pair,
275*0fca6ea1SDimitry Andric                             __nat>&& __p) noexcept(is_nothrow_move_assignable<first_type>::value &&
276*0fca6ea1SDimitry Andric                                                    is_nothrow_move_assignable<second_type>::value) {
27706c3fb27SDimitry Andric     first  = std::forward<first_type>(__p.first);
27806c3fb27SDimitry Andric     second = std::forward<second_type>(__p.second);
279fe6060f1SDimitry Andric     return *this;
280fe6060f1SDimitry Andric   }
281fe6060f1SDimitry Andric 
282cb14a3feSDimitry Andric   template <
283cb14a3feSDimitry Andric       class _U1,
284cb14a3feSDimitry Andric       class _U2,
285*0fca6ea1SDimitry Andric       __enable_if_t<is_assignable<first_type&, _U1 const&>::value && is_assignable<second_type&, _U2 const&>::value,
286*0fca6ea1SDimitry Andric                     int> = 0>
287*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair& operator=(pair<_U1, _U2> const& __p) {
288*0fca6ea1SDimitry Andric     first  = __p.first;
289*0fca6ea1SDimitry Andric     second = __p.second;
290*0fca6ea1SDimitry Andric     return *this;
291*0fca6ea1SDimitry Andric   }
292*0fca6ea1SDimitry Andric 
293*0fca6ea1SDimitry Andric   template <class _U1,
294*0fca6ea1SDimitry Andric             class _U2,
295*0fca6ea1SDimitry Andric             __enable_if_t<is_assignable<first_type&, _U1>::value && is_assignable<second_type&, _U2>::value, int> = 0>
296cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair& operator=(pair<_U1, _U2>&& __p) {
29706c3fb27SDimitry Andric     first  = std::forward<_U1>(__p.first);
29806c3fb27SDimitry Andric     second = std::forward<_U2>(__p.second);
29906c3fb27SDimitry Andric     return *this;
30006c3fb27SDimitry Andric   }
30106c3fb27SDimitry Andric 
30206c3fb27SDimitry Andric #  if _LIBCPP_STD_VER >= 23
303*0fca6ea1SDimitry Andric   template <class = void>
304cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const pair& operator=(pair const& __p) const
305cb14a3feSDimitry Andric       noexcept(is_nothrow_copy_assignable_v<const first_type> && is_nothrow_copy_assignable_v<const second_type>)
306cb14a3feSDimitry Andric     requires(is_copy_assignable_v<const first_type> && is_copy_assignable_v<const second_type>)
307cb14a3feSDimitry Andric   {
308bdd1243dSDimitry Andric     first  = __p.first;
309bdd1243dSDimitry Andric     second = __p.second;
310bdd1243dSDimitry Andric     return *this;
311bdd1243dSDimitry Andric   }
312bdd1243dSDimitry Andric 
313*0fca6ea1SDimitry Andric   template <class = void>
314cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const pair& operator=(pair&& __p) const
315bdd1243dSDimitry Andric       noexcept(is_nothrow_assignable_v<const first_type&, first_type> &&
316bdd1243dSDimitry Andric                is_nothrow_assignable_v<const second_type&, second_type>)
317cb14a3feSDimitry Andric     requires(is_assignable_v<const first_type&, first_type> && is_assignable_v<const second_type&, second_type>)
318cb14a3feSDimitry Andric   {
319bdd1243dSDimitry Andric     first  = std::forward<first_type>(__p.first);
320bdd1243dSDimitry Andric     second = std::forward<second_type>(__p.second);
321bdd1243dSDimitry Andric     return *this;
322bdd1243dSDimitry Andric   }
323bdd1243dSDimitry Andric 
324bdd1243dSDimitry Andric   template <class _U1, class _U2>
325cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const pair& operator=(const pair<_U1, _U2>& __p) const
326cb14a3feSDimitry Andric     requires(is_assignable_v<const first_type&, const _U1&> && is_assignable_v<const second_type&, const _U2&>)
327cb14a3feSDimitry Andric   {
328bdd1243dSDimitry Andric     first  = __p.first;
329bdd1243dSDimitry Andric     second = __p.second;
330bdd1243dSDimitry Andric     return *this;
331bdd1243dSDimitry Andric   }
332bdd1243dSDimitry Andric 
333bdd1243dSDimitry Andric   template <class _U1, class _U2>
334cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const pair& operator=(pair<_U1, _U2>&& __p) const
335cb14a3feSDimitry Andric     requires(is_assignable_v<const first_type&, _U1> && is_assignable_v<const second_type&, _U2>)
336cb14a3feSDimitry Andric   {
337bdd1243dSDimitry Andric     first  = std::forward<_U1>(__p.first);
338bdd1243dSDimitry Andric     second = std::forward<_U2>(__p.second);
339bdd1243dSDimitry Andric     return *this;
340bdd1243dSDimitry Andric   }
341bdd1243dSDimitry Andric 
342*0fca6ea1SDimitry Andric   template <__pair_like_no_subrange _PairLike>
343*0fca6ea1SDimitry Andric     requires(__different_from<_PairLike, pair> &&
34406c3fb27SDimitry Andric              is_assignable_v<first_type&, decltype(std::get<0>(std::declval<_PairLike>()))> &&
34506c3fb27SDimitry Andric              is_assignable_v<second_type&, decltype(std::get<1>(std::declval<_PairLike>()))>)
34606c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr pair& operator=(_PairLike&& __p) {
34706c3fb27SDimitry Andric     first  = std::get<0>(std::forward<_PairLike>(__p));
34806c3fb27SDimitry Andric     second = std::get<1>(std::forward<_PairLike>(__p));
349fe6060f1SDimitry Andric     return *this;
350fe6060f1SDimitry Andric   }
351fe6060f1SDimitry Andric 
352*0fca6ea1SDimitry Andric   template <__pair_like_no_subrange _PairLike>
353*0fca6ea1SDimitry Andric     requires(__different_from<_PairLike, pair> &&
35406c3fb27SDimitry Andric              is_assignable_v<first_type const&, decltype(std::get<0>(std::declval<_PairLike>()))> &&
35506c3fb27SDimitry Andric              is_assignable_v<second_type const&, decltype(std::get<1>(std::declval<_PairLike>()))>)
35606c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr pair const& operator=(_PairLike&& __p) const {
35706c3fb27SDimitry Andric     first  = std::get<0>(std::forward<_PairLike>(__p));
35806c3fb27SDimitry Andric     second = std::get<1>(std::forward<_PairLike>(__p));
35906c3fb27SDimitry Andric     return *this;
36006c3fb27SDimitry Andric   }
36106c3fb27SDimitry Andric #  endif // _LIBCPP_STD_VER >= 23
36206c3fb27SDimitry Andric 
36306c3fb27SDimitry Andric   // Prior to C++23, we provide an approximation of constructors and assignment operators from
36406c3fb27SDimitry Andric   // pair-like types. This was historically provided as an extension.
36506c3fb27SDimitry Andric #  if _LIBCPP_STD_VER < 23
36606c3fb27SDimitry Andric   // from std::tuple
367*0fca6ea1SDimitry Andric   template <class _U1,
368cb14a3feSDimitry Andric             class _U2,
369*0fca6ea1SDimitry Andric             __enable_if_t<is_convertible<_U1 const&, _T1>::value && is_convertible<_U2 const&, _T2>::value, int> = 0>
370cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(tuple<_U1, _U2> const& __p)
371cb14a3feSDimitry Andric       : first(std::get<0>(__p)), second(std::get<1>(__p)) {}
37206c3fb27SDimitry Andric 
373*0fca6ea1SDimitry Andric   template < class _U1,
374cb14a3feSDimitry Andric              class _U2,
375cb14a3feSDimitry Andric              __enable_if_t<is_constructible<_T1, _U1 const&>::value && is_constructible<_T2, _U2 const&>::value &&
376*0fca6ea1SDimitry Andric                                !(is_convertible<_U1 const&, _T1>::value && is_convertible<_U2 const&, _T2>::value),
377*0fca6ea1SDimitry Andric                            int> = 0>
378cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(tuple<_U1, _U2> const& __p)
379cb14a3feSDimitry Andric       : first(std::get<0>(__p)), second(std::get<1>(__p)) {}
38006c3fb27SDimitry Andric 
381cb14a3feSDimitry Andric   template <class _U1,
382cb14a3feSDimitry Andric             class _U2,
383*0fca6ea1SDimitry Andric             __enable_if_t<is_convertible<_U1, _T1>::value && is_convertible<_U2, _T2>::value, int> = 0>
384cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(tuple<_U1, _U2>&& __p)
385cb14a3feSDimitry Andric       : first(std::get<0>(std::move(__p))), second(std::get<1>(std::move(__p))) {}
38606c3fb27SDimitry Andric 
387cb14a3feSDimitry Andric   template <class _U1,
388cb14a3feSDimitry Andric             class _U2,
389cb14a3feSDimitry Andric             __enable_if_t<is_constructible<_T1, _U1>::value && is_constructible<_T2, _U2>::value &&
390*0fca6ea1SDimitry Andric                           !(is_convertible<_U1, _T1>::value && is_convertible<_U2, _T2>::value) > = 0>
391cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(tuple<_U1, _U2>&& __p)
392cb14a3feSDimitry Andric       : first(std::get<0>(std::move(__p))), second(std::get<1>(std::move(__p))) {}
39306c3fb27SDimitry Andric 
394*0fca6ea1SDimitry Andric   template <class _U1,
395cb14a3feSDimitry Andric             class _U2,
396*0fca6ea1SDimitry Andric             __enable_if_t<is_assignable<_T1&, _U1 const&>::value && is_assignable<_T2&, _U2 const&>::value, int> = 0>
397cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair& operator=(tuple<_U1, _U2> const& __p) {
39806c3fb27SDimitry Andric     first  = std::get<0>(__p);
39906c3fb27SDimitry Andric     second = std::get<1>(__p);
40006c3fb27SDimitry Andric     return *this;
40106c3fb27SDimitry Andric   }
40206c3fb27SDimitry Andric 
403cb14a3feSDimitry Andric   template <class _U1,
404cb14a3feSDimitry Andric             class _U2,
405*0fca6ea1SDimitry Andric             __enable_if_t<is_assignable<_T1&, _U1&&>::value && is_assignable<_T2&, _U2&&>::value, int> = 0>
406cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair& operator=(tuple<_U1, _U2>&& __p) {
40706c3fb27SDimitry Andric     first  = std::get<0>(std::move(__p));
40806c3fb27SDimitry Andric     second = std::get<1>(std::move(__p));
40906c3fb27SDimitry Andric     return *this;
41006c3fb27SDimitry Andric   }
41106c3fb27SDimitry Andric 
41206c3fb27SDimitry Andric   // from std::array
413*0fca6ea1SDimitry Andric   template <class _Up,
414*0fca6ea1SDimitry Andric             __enable_if_t<is_convertible<_Up const&, _T1>::value && is_convertible<_Up const&, _T2>::value, int> = 0>
415cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(array<_Up, 2> const& __p) : first(__p[0]), second(__p[1]) {}
41606c3fb27SDimitry Andric 
417*0fca6ea1SDimitry Andric   template <class _Up,
418cb14a3feSDimitry Andric             __enable_if_t<is_constructible<_T1, _Up const&>::value && is_constructible<_T2, _Up const&>::value &&
419*0fca6ea1SDimitry Andric                               !(is_convertible<_Up const&, _T1>::value && is_convertible<_Up const&, _T2>::value),
420*0fca6ea1SDimitry Andric                           int> = 0>
421cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(array<_Up, 2> const& __p)
422cb14a3feSDimitry Andric       : first(__p[0]), second(__p[1]) {}
42306c3fb27SDimitry Andric 
424*0fca6ea1SDimitry Andric   template <class _Up, __enable_if_t< is_convertible<_Up, _T1>::value && is_convertible<_Up, _T2>::value, int> = 0>
425cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair(array<_Up, 2>&& __p)
426cb14a3feSDimitry Andric       : first(std::move(__p)[0]), second(std::move(__p)[1]) {}
42706c3fb27SDimitry Andric 
428cb14a3feSDimitry Andric   template <class _Up,
429cb14a3feSDimitry Andric             __enable_if_t<is_constructible<_T1, _Up>::value && is_constructible<_T2, _Up>::value &&
430*0fca6ea1SDimitry Andric                               !(is_convertible<_Up, _T1>::value && is_convertible<_Up, _T2>::value),
431*0fca6ea1SDimitry Andric                           int> = 0>
432cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit pair(array<_Up, 2>&& __p)
433cb14a3feSDimitry Andric       : first(std::move(__p)[0]), second(std::move(__p)[1]) {}
43406c3fb27SDimitry Andric 
435*0fca6ea1SDimitry Andric   template <class _Up,
436*0fca6ea1SDimitry Andric             __enable_if_t<is_assignable<_T1&, _Up const&>::value && is_assignable<_T2&, _Up const&>::value, int> = 0>
437cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair& operator=(array<_Up, 2> const& __p) {
43806c3fb27SDimitry Andric     first  = std::get<0>(__p);
43906c3fb27SDimitry Andric     second = std::get<1>(__p);
44006c3fb27SDimitry Andric     return *this;
44106c3fb27SDimitry Andric   }
44206c3fb27SDimitry Andric 
443*0fca6ea1SDimitry Andric   template <class _Up, __enable_if_t<is_assignable<_T1&, _Up>::value && is_assignable<_T2&, _Up>::value, int> = 0>
444cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair& operator=(array<_Up, 2>&& __p) {
44506c3fb27SDimitry Andric     first  = std::get<0>(std::move(__p));
44606c3fb27SDimitry Andric     second = std::get<1>(std::move(__p));
44706c3fb27SDimitry Andric     return *this;
44806c3fb27SDimitry Andric   }
44906c3fb27SDimitry Andric #  endif // _LIBCPP_STD_VER < 23
45006c3fb27SDimitry Andric #endif   // _LIBCPP_CXX03_LANG
45106c3fb27SDimitry Andric 
452cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(pair& __p)
453*0fca6ea1SDimitry Andric       _NOEXCEPT_(__is_nothrow_swappable_v<first_type>&& __is_nothrow_swappable_v<second_type>) {
45406c3fb27SDimitry Andric     using std::swap;
455fe6060f1SDimitry Andric     swap(first, __p.first);
456fe6060f1SDimitry Andric     swap(second, __p.second);
457fe6060f1SDimitry Andric   }
458bdd1243dSDimitry Andric 
45906c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 23
460cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void swap(const pair& __p) const
461*0fca6ea1SDimitry Andric       noexcept(__is_nothrow_swappable_v<const first_type> && __is_nothrow_swappable_v<const second_type>) {
462bdd1243dSDimitry Andric     using std::swap;
463bdd1243dSDimitry Andric     swap(first, __p.first);
464bdd1243dSDimitry Andric     swap(second, __p.second);
465bdd1243dSDimitry Andric   }
466bdd1243dSDimitry Andric #endif
467fe6060f1SDimitry Andric 
468cb14a3feSDimitry Andric private:
469fe6060f1SDimitry Andric #ifndef _LIBCPP_CXX03_LANG
470fe6060f1SDimitry Andric   template <class... _Args1, class... _Args2, size_t... _I1, size_t... _I2>
47106c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
472fe6060f1SDimitry Andric   pair(piecewise_construct_t,
473cb14a3feSDimitry Andric        tuple<_Args1...>& __first_args,
474cb14a3feSDimitry Andric        tuple<_Args2...>& __second_args,
475cb14a3feSDimitry Andric        __tuple_indices<_I1...>,
476*0fca6ea1SDimitry Andric        __tuple_indices<_I2...>)
477*0fca6ea1SDimitry Andric       : first(std::forward<_Args1>(std::get<_I1>(__first_args))...),
478*0fca6ea1SDimitry Andric         second(std::forward<_Args2>(std::get<_I2>(__second_args))...) {}
479fe6060f1SDimitry Andric #endif
480fe6060f1SDimitry Andric };
481fe6060f1SDimitry Andric 
48206c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 17
483fe6060f1SDimitry Andric template <class _T1, class _T2>
484fe6060f1SDimitry Andric pair(_T1, _T2) -> pair<_T1, _T2>;
485349cc55cSDimitry Andric #endif
486349cc55cSDimitry Andric 
487349cc55cSDimitry Andric // [pairs.spec], specialized algorithms
488fe6060f1SDimitry Andric 
48906c3fb27SDimitry Andric template <class _T1, class _T2, class _U1, class _U2>
490cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
491cb14a3feSDimitry Andric operator==(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
492fe6060f1SDimitry Andric   return __x.first == __y.first && __x.second == __y.second;
493fe6060f1SDimitry Andric }
494fe6060f1SDimitry Andric 
49506c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
496349cc55cSDimitry Andric 
49706c3fb27SDimitry Andric template <class _T1, class _T2, class _U1, class _U2>
498cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr common_comparison_category_t< __synth_three_way_result<_T1, _U1>,
49906c3fb27SDimitry Andric                                                               __synth_three_way_result<_T2, _U2> >
500cb14a3feSDimitry Andric operator<=>(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
50106c3fb27SDimitry Andric   if (auto __c = std::__synth_three_way(__x.first, __y.first); __c != 0) {
502349cc55cSDimitry Andric     return __c;
503349cc55cSDimitry Andric   }
50406c3fb27SDimitry Andric   return std::__synth_three_way(__x.second, __y.second);
505349cc55cSDimitry Andric }
506349cc55cSDimitry Andric 
50706c3fb27SDimitry Andric #else // _LIBCPP_STD_VER >= 20
508349cc55cSDimitry Andric 
50906c3fb27SDimitry Andric template <class _T1, class _T2, class _U1, class _U2>
510cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
511cb14a3feSDimitry Andric operator!=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
512fe6060f1SDimitry Andric   return !(__x == __y);
513fe6060f1SDimitry Andric }
514fe6060f1SDimitry Andric 
51506c3fb27SDimitry Andric template <class _T1, class _T2, class _U1, class _U2>
516cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
517cb14a3feSDimitry Andric operator<(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
518fe6060f1SDimitry Andric   return __x.first < __y.first || (!(__y.first < __x.first) && __x.second < __y.second);
519fe6060f1SDimitry Andric }
520fe6060f1SDimitry Andric 
52106c3fb27SDimitry Andric template <class _T1, class _T2, class _U1, class _U2>
522cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
523cb14a3feSDimitry Andric operator>(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
524fe6060f1SDimitry Andric   return __y < __x;
525fe6060f1SDimitry Andric }
526fe6060f1SDimitry Andric 
52706c3fb27SDimitry Andric template <class _T1, class _T2, class _U1, class _U2>
528cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
529cb14a3feSDimitry Andric operator>=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
530fe6060f1SDimitry Andric   return !(__x < __y);
531fe6060f1SDimitry Andric }
532fe6060f1SDimitry Andric 
53306c3fb27SDimitry Andric template <class _T1, class _T2, class _U1, class _U2>
534cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 bool
535cb14a3feSDimitry Andric operator<=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
536fe6060f1SDimitry Andric   return !(__y < __x);
537fe6060f1SDimitry Andric }
538fe6060f1SDimitry Andric 
53906c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
54081ad6265SDimitry Andric 
54106c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 23
54281ad6265SDimitry Andric template <class _T1, class _T2, class _U1, class _U2, template <class> class _TQual, template <class> class _UQual>
543cb14a3feSDimitry Andric   requires requires {
544cb14a3feSDimitry Andric     typename pair<common_reference_t<_TQual<_T1>, _UQual<_U1>>, common_reference_t<_TQual<_T2>, _UQual<_U2>>>;
545cb14a3feSDimitry Andric   }
54681ad6265SDimitry Andric struct basic_common_reference<pair<_T1, _T2>, pair<_U1, _U2>, _TQual, _UQual> {
547cb14a3feSDimitry Andric   using type = pair<common_reference_t<_TQual<_T1>, _UQual<_U1>>, common_reference_t<_TQual<_T2>, _UQual<_U2>>>;
54881ad6265SDimitry Andric };
54981ad6265SDimitry Andric 
55081ad6265SDimitry Andric template <class _T1, class _T2, class _U1, class _U2>
55181ad6265SDimitry Andric   requires requires { typename pair<common_type_t<_T1, _U1>, common_type_t<_T2, _U2>>; }
55281ad6265SDimitry Andric struct common_type<pair<_T1, _T2>, pair<_U1, _U2>> {
55381ad6265SDimitry Andric   using type = pair<common_type_t<_T1, _U1>, common_type_t<_T2, _U2>>;
55481ad6265SDimitry Andric };
55506c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 23
556349cc55cSDimitry Andric 
557*0fca6ea1SDimitry Andric template <class _T1, class _T2, __enable_if_t<__is_swappable_v<_T1> && __is_swappable_v<_T2>, int> = 0>
558cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y)
559*0fca6ea1SDimitry Andric     _NOEXCEPT_(__is_nothrow_swappable_v<_T1>&& __is_nothrow_swappable_v<_T2>) {
560fe6060f1SDimitry Andric   __x.swap(__y);
561fe6060f1SDimitry Andric }
562fe6060f1SDimitry Andric 
56306c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 23
564bdd1243dSDimitry Andric template <class _T1, class _T2>
565*0fca6ea1SDimitry Andric   requires(__is_swappable_v<const _T1> && __is_swappable_v<const _T2>)
566cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void
567cb14a3feSDimitry Andric swap(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) noexcept(noexcept(__x.swap(__y))) {
568bdd1243dSDimitry Andric   __x.swap(__y);
569bdd1243dSDimitry Andric }
570bdd1243dSDimitry Andric #endif
571fe6060f1SDimitry Andric 
572fe6060f1SDimitry Andric template <class _T1, class _T2>
573*0fca6ea1SDimitry Andric inline _LIBCPP_HIDE_FROM_ABI
574*0fca6ea1SDimitry Andric _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type>
575cb14a3feSDimitry Andric make_pair(_T1&& __t1, _T2&& __t2) {
576cb14a3feSDimitry Andric   return pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type>(
577cb14a3feSDimitry Andric       std::forward<_T1>(__t1), std::forward<_T2>(__t2));
578fe6060f1SDimitry Andric }
579fe6060f1SDimitry Andric 
580fe6060f1SDimitry Andric template <class _T1, class _T2>
581cb14a3feSDimitry Andric struct _LIBCPP_TEMPLATE_VIS tuple_size<pair<_T1, _T2> > : public integral_constant<size_t, 2> {};
582fe6060f1SDimitry Andric 
583fe6060f1SDimitry Andric template <size_t _Ip, class _T1, class _T2>
584cb14a3feSDimitry Andric struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, pair<_T1, _T2> > {
585fe6060f1SDimitry Andric   static_assert(_Ip < 2, "Index out of bounds in std::tuple_element<std::pair<T1, T2>>");
586fe6060f1SDimitry Andric };
587fe6060f1SDimitry Andric 
588fe6060f1SDimitry Andric template <class _T1, class _T2>
589cb14a3feSDimitry Andric struct _LIBCPP_TEMPLATE_VIS tuple_element<0, pair<_T1, _T2> > {
59006c3fb27SDimitry Andric   using type _LIBCPP_NODEBUG = _T1;
591fe6060f1SDimitry Andric };
592fe6060f1SDimitry Andric 
593fe6060f1SDimitry Andric template <class _T1, class _T2>
594cb14a3feSDimitry Andric struct _LIBCPP_TEMPLATE_VIS tuple_element<1, pair<_T1, _T2> > {
59506c3fb27SDimitry Andric   using type _LIBCPP_NODEBUG = _T2;
596fe6060f1SDimitry Andric };
597fe6060f1SDimitry Andric 
598cb14a3feSDimitry Andric template <size_t _Ip>
599cb14a3feSDimitry Andric struct __get_pair;
600fe6060f1SDimitry Andric 
601fe6060f1SDimitry Andric template <>
602cb14a3feSDimitry Andric struct __get_pair<0> {
603fe6060f1SDimitry Andric   template <class _T1, class _T2>
604cb14a3feSDimitry Andric   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _T1& get(pair<_T1, _T2>& __p) _NOEXCEPT {
605cb14a3feSDimitry Andric     return __p.first;
606cb14a3feSDimitry Andric   }
607fe6060f1SDimitry Andric 
608fe6060f1SDimitry Andric   template <class _T1, class _T2>
609cb14a3feSDimitry Andric   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _T1& get(const pair<_T1, _T2>& __p) _NOEXCEPT {
610cb14a3feSDimitry Andric     return __p.first;
611cb14a3feSDimitry Andric   }
612fe6060f1SDimitry Andric 
613fe6060f1SDimitry Andric   template <class _T1, class _T2>
614cb14a3feSDimitry Andric   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _T1&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {
615cb14a3feSDimitry Andric     return std::forward<_T1>(__p.first);
616cb14a3feSDimitry Andric   }
617fe6060f1SDimitry Andric 
618fe6060f1SDimitry Andric   template <class _T1, class _T2>
619cb14a3feSDimitry Andric   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _T1&& get(const pair<_T1, _T2>&& __p) _NOEXCEPT {
620cb14a3feSDimitry Andric     return std::forward<const _T1>(__p.first);
621cb14a3feSDimitry Andric   }
622fe6060f1SDimitry Andric };
623fe6060f1SDimitry Andric 
624fe6060f1SDimitry Andric template <>
625cb14a3feSDimitry Andric struct __get_pair<1> {
626fe6060f1SDimitry Andric   template <class _T1, class _T2>
627cb14a3feSDimitry Andric   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _T2& get(pair<_T1, _T2>& __p) _NOEXCEPT {
628cb14a3feSDimitry Andric     return __p.second;
629cb14a3feSDimitry Andric   }
630fe6060f1SDimitry Andric 
631fe6060f1SDimitry Andric   template <class _T1, class _T2>
632cb14a3feSDimitry Andric   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _T2& get(const pair<_T1, _T2>& __p) _NOEXCEPT {
633cb14a3feSDimitry Andric     return __p.second;
634cb14a3feSDimitry Andric   }
635fe6060f1SDimitry Andric 
636fe6060f1SDimitry Andric   template <class _T1, class _T2>
637cb14a3feSDimitry Andric   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _T2&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {
638cb14a3feSDimitry Andric     return std::forward<_T2>(__p.second);
639cb14a3feSDimitry Andric   }
640fe6060f1SDimitry Andric 
641fe6060f1SDimitry Andric   template <class _T1, class _T2>
642cb14a3feSDimitry Andric   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _T2&& get(const pair<_T1, _T2>&& __p) _NOEXCEPT {
643cb14a3feSDimitry Andric     return std::forward<const _T2>(__p.second);
644cb14a3feSDimitry Andric   }
645fe6060f1SDimitry Andric };
646fe6060f1SDimitry Andric 
647fe6060f1SDimitry Andric template <size_t _Ip, class _T1, class _T2>
648cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Ip, pair<_T1, _T2> >::type&
649cb14a3feSDimitry Andric get(pair<_T1, _T2>& __p) _NOEXCEPT {
650fe6060f1SDimitry Andric   return __get_pair<_Ip>::get(__p);
651fe6060f1SDimitry Andric }
652fe6060f1SDimitry Andric 
653fe6060f1SDimitry Andric template <size_t _Ip, class _T1, class _T2>
654cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Ip, pair<_T1, _T2> >::type&
655cb14a3feSDimitry Andric get(const pair<_T1, _T2>& __p) _NOEXCEPT {
656fe6060f1SDimitry Andric   return __get_pair<_Ip>::get(__p);
657fe6060f1SDimitry Andric }
658fe6060f1SDimitry Andric 
659fe6060f1SDimitry Andric template <size_t _Ip, class _T1, class _T2>
660cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Ip, pair<_T1, _T2> >::type&&
661cb14a3feSDimitry Andric get(pair<_T1, _T2>&& __p) _NOEXCEPT {
66206c3fb27SDimitry Andric   return __get_pair<_Ip>::get(std::move(__p));
663fe6060f1SDimitry Andric }
664fe6060f1SDimitry Andric 
665fe6060f1SDimitry Andric template <size_t _Ip, class _T1, class _T2>
666cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Ip, pair<_T1, _T2> >::type&&
667cb14a3feSDimitry Andric get(const pair<_T1, _T2>&& __p) _NOEXCEPT {
66806c3fb27SDimitry Andric   return __get_pair<_Ip>::get(std::move(__p));
669fe6060f1SDimitry Andric }
670fe6060f1SDimitry Andric 
67106c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 14
672fe6060f1SDimitry Andric template <class _T1, class _T2>
673cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI constexpr _T1& get(pair<_T1, _T2>& __p) _NOEXCEPT {
674fe6060f1SDimitry Andric   return __get_pair<0>::get(__p);
675fe6060f1SDimitry Andric }
676fe6060f1SDimitry Andric 
677fe6060f1SDimitry Andric template <class _T1, class _T2>
678cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const& get(pair<_T1, _T2> const& __p) _NOEXCEPT {
679fe6060f1SDimitry Andric   return __get_pair<0>::get(__p);
680fe6060f1SDimitry Andric }
681fe6060f1SDimitry Andric 
682fe6060f1SDimitry Andric template <class _T1, class _T2>
683cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI constexpr _T1&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {
68406c3fb27SDimitry Andric   return __get_pair<0>::get(std::move(__p));
685fe6060f1SDimitry Andric }
686fe6060f1SDimitry Andric 
687fe6060f1SDimitry Andric template <class _T1, class _T2>
688cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const&& get(pair<_T1, _T2> const&& __p) _NOEXCEPT {
68906c3fb27SDimitry Andric   return __get_pair<0>::get(std::move(__p));
690fe6060f1SDimitry Andric }
691fe6060f1SDimitry Andric 
692fe6060f1SDimitry Andric template <class _T1, class _T2>
693cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI constexpr _T1& get(pair<_T2, _T1>& __p) _NOEXCEPT {
694fe6060f1SDimitry Andric   return __get_pair<1>::get(__p);
695fe6060f1SDimitry Andric }
696fe6060f1SDimitry Andric 
697fe6060f1SDimitry Andric template <class _T1, class _T2>
698cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const& get(pair<_T2, _T1> const& __p) _NOEXCEPT {
699fe6060f1SDimitry Andric   return __get_pair<1>::get(__p);
700fe6060f1SDimitry Andric }
701fe6060f1SDimitry Andric 
702fe6060f1SDimitry Andric template <class _T1, class _T2>
703cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI constexpr _T1&& get(pair<_T2, _T1>&& __p) _NOEXCEPT {
70406c3fb27SDimitry Andric   return __get_pair<1>::get(std::move(__p));
705fe6060f1SDimitry Andric }
706fe6060f1SDimitry Andric 
707fe6060f1SDimitry Andric template <class _T1, class _T2>
708cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const&& get(pair<_T2, _T1> const&& __p) _NOEXCEPT {
70906c3fb27SDimitry Andric   return __get_pair<1>::get(std::move(__p));
710fe6060f1SDimitry Andric }
711fe6060f1SDimitry Andric 
71206c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 14
713fe6060f1SDimitry Andric 
714fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
715fe6060f1SDimitry Andric 
71606c3fb27SDimitry Andric _LIBCPP_POP_MACROS
71706c3fb27SDimitry Andric 
718fe6060f1SDimitry Andric #endif // _LIBCPP___UTILITY_PAIR_H
719