xref: /freebsd/contrib/llvm-project/libcxx/include/__cxx03/__utility/pair.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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___CXX03___UTILITY_PAIR_H
10 #define _LIBCPP___CXX03___UTILITY_PAIR_H
11 
12 #include <__cxx03/__config>
13 #include <__cxx03/__fwd/array.h>
14 #include <__cxx03/__fwd/pair.h>
15 #include <__cxx03/__fwd/tuple.h>
16 #include <__cxx03/__tuple/sfinae_helpers.h>
17 #include <__cxx03/__tuple/tuple_element.h>
18 #include <__cxx03/__tuple/tuple_indices.h>
19 #include <__cxx03/__tuple/tuple_like_no_subrange.h>
20 #include <__cxx03/__tuple/tuple_size.h>
21 #include <__cxx03/__type_traits/common_type.h>
22 #include <__cxx03/__type_traits/conditional.h>
23 #include <__cxx03/__type_traits/decay.h>
24 #include <__cxx03/__type_traits/integral_constant.h>
25 #include <__cxx03/__type_traits/is_assignable.h>
26 #include <__cxx03/__type_traits/is_constructible.h>
27 #include <__cxx03/__type_traits/is_convertible.h>
28 #include <__cxx03/__type_traits/is_implicitly_default_constructible.h>
29 #include <__cxx03/__type_traits/is_nothrow_assignable.h>
30 #include <__cxx03/__type_traits/is_nothrow_constructible.h>
31 #include <__cxx03/__type_traits/is_reference.h>
32 #include <__cxx03/__type_traits/is_same.h>
33 #include <__cxx03/__type_traits/is_swappable.h>
34 #include <__cxx03/__type_traits/is_trivially_relocatable.h>
35 #include <__cxx03/__type_traits/nat.h>
36 #include <__cxx03/__type_traits/remove_cvref.h>
37 #include <__cxx03/__type_traits/unwrap_ref.h>
38 #include <__cxx03/__utility/declval.h>
39 #include <__cxx03/__utility/forward.h>
40 #include <__cxx03/__utility/move.h>
41 #include <__cxx03/__utility/piecewise_construct.h>
42 #include <__cxx03/cstddef>
43 
44 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
45 #  pragma GCC system_header
46 #endif
47 
48 _LIBCPP_PUSH_MACROS
49 #include <__cxx03/__undef_macros>
50 
51 _LIBCPP_BEGIN_NAMESPACE_STD
52 
53 template <class, class>
54 struct __non_trivially_copyable_base {
__non_trivially_copyable_base__non_trivially_copyable_base55   _LIBCPP_HIDE_FROM_ABI __non_trivially_copyable_base() _NOEXCEPT {}
__non_trivially_copyable_base__non_trivially_copyable_base56   _LIBCPP_HIDE_FROM_ABI __non_trivially_copyable_base(__non_trivially_copyable_base const&) _NOEXCEPT {}
57 };
58 
59 template <class _T1, class _T2>
60 struct _LIBCPP_TEMPLATE_VIS pair
61 #if defined(_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR)
62     : private __non_trivially_copyable_base<_T1, _T2>
63 #endif
64 {
65   using first_type  = _T1;
66   using second_type = _T2;
67 
68   _T1 first;
69   _T2 second;
70 
71   using __trivially_relocatable =
72       __conditional_t<__libcpp_is_trivially_relocatable<_T1>::value && __libcpp_is_trivially_relocatable<_T2>::value,
73                       pair,
74                       void>;
75 
76   _LIBCPP_HIDE_FROM_ABI pair(pair const&) = default;
77   _LIBCPP_HIDE_FROM_ABI pair(pair&&)      = default;
78 
79   // When we are requested for pair to be trivially copyable by the ABI macro, we use defaulted members
80   // if it is both legal to do it (i.e. no references) and we have a way to actually implement it, which requires
81   // the __enable_if__ attribute before C++20.
82 #ifdef _LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR
83   // FIXME: This should really just be a static constexpr variable. It's in a struct to avoid gdb printing the value
84   // when printing a pair
85   struct __has_defaulted_members {
86     static const bool value = !is_reference<first_type>::value && !is_reference<second_type>::value;
87   };
88 #  if __has_attribute(__enable_if__)
89   _LIBCPP_HIDE_FROM_ABI pair& operator=(const pair&)
90       __attribute__((__enable_if__(__has_defaulted_members::value, ""))) = default;
91 
92   _LIBCPP_HIDE_FROM_ABI pair& operator=(pair&&)
93       __attribute__((__enable_if__(__has_defaulted_members::value, ""))) = default;
94 #  else
95 #    error "_LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR isn't supported with this compiler"
96 #  endif
97 #else
98   struct __has_defaulted_members {
99     static const bool value = false;
100   };
101 #endif // defined(_LIBCPP_ABI_TRIVIALLY_COPYABLE_PAIR) && __has_attribute(__enable_if__)
102 
pairpair103   _LIBCPP_HIDE_FROM_ABI pair() : first(), second() {}
104 
pairpair105   _LIBCPP_HIDE_FROM_ABI pair(_T1 const& __t1, _T2 const& __t2) : first(__t1), second(__t2) {}
106 
107   template <class _U1, class _U2>
pairpair108   _LIBCPP_HIDE_FROM_ABI pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) {}
109 
110   _LIBCPP_HIDE_FROM_ABI pair& operator=(pair const& __p) {
111     first  = __p.first;
112     second = __p.second;
113     return *this;
114   }
115 
116   // Extension: This is provided in C++03 because it allows properly handling the
117   //            assignment to a pair containing references, which would be a hard
118   //            error otherwise.
119   template <
120       class _U1,
121       class _U2,
122       __enable_if_t<is_assignable<first_type&, _U1 const&>::value && is_assignable<second_type&, _U2 const&>::value,
123                     int> = 0>
124   _LIBCPP_HIDE_FROM_ABI pair& operator=(pair<_U1, _U2> const& __p) {
125     first  = __p.first;
126     second = __p.second;
127     return *this;
128   }
129 
swappair130   _LIBCPP_HIDE_FROM_ABI void swap(pair& __p) {
131     using std::swap;
132     swap(first, __p.first);
133     swap(second, __p.second);
134   }
135 };
136 
137 // [pairs.spec], specialized algorithms
138 
139 template <class _T1, class _T2, class _U1, class _U2>
140 inline _LIBCPP_HIDE_FROM_ABI bool operator==(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
141   return __x.first == __y.first && __x.second == __y.second;
142 }
143 
144 template <class _T1, class _T2, class _U1, class _U2>
145 inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
146   return !(__x == __y);
147 }
148 
149 template <class _T1, class _T2, class _U1, class _U2>
150 inline _LIBCPP_HIDE_FROM_ABI bool operator<(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
151   return __x.first < __y.first || (!(__y.first < __x.first) && __x.second < __y.second);
152 }
153 
154 template <class _T1, class _T2, class _U1, class _U2>
155 inline _LIBCPP_HIDE_FROM_ABI bool operator>(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
156   return __y < __x;
157 }
158 
159 template <class _T1, class _T2, class _U1, class _U2>
160 inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
161   return !(__x < __y);
162 }
163 
164 template <class _T1, class _T2, class _U1, class _U2>
165 inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const pair<_T1, _T2>& __x, const pair<_U1, _U2>& __y) {
166   return !(__y < __x);
167 }
168 
169 template <class _T1, class _T2, __enable_if_t<__is_swappable_v<_T1> && __is_swappable_v<_T2>, int> = 0>
swap(pair<_T1,_T2> & __x,pair<_T1,_T2> & __y)170 inline _LIBCPP_HIDE_FROM_ABI void swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y) {
171   __x.swap(__y);
172 }
173 
174 template <class _T1, class _T2>
175 inline _LIBCPP_HIDE_FROM_ABI pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type>
make_pair(_T1 && __t1,_T2 && __t2)176 make_pair(_T1&& __t1, _T2&& __t2) {
177   return pair<typename __unwrap_ref_decay<_T1>::type, typename __unwrap_ref_decay<_T2>::type>(
178       std::forward<_T1>(__t1), std::forward<_T2>(__t2));
179 }
180 
181 template <class _T1, class _T2>
182 struct _LIBCPP_TEMPLATE_VIS tuple_size<pair<_T1, _T2> > : public integral_constant<size_t, 2> {};
183 
184 template <size_t _Ip, class _T1, class _T2>
185 struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, pair<_T1, _T2> > {
186   static_assert(_Ip < 2, "Index out of bounds in std::tuple_element<std::pair<T1, T2>>");
187 };
188 
189 template <class _T1, class _T2>
190 struct _LIBCPP_TEMPLATE_VIS tuple_element<0, pair<_T1, _T2> > {
191   using type _LIBCPP_NODEBUG = _T1;
192 };
193 
194 template <class _T1, class _T2>
195 struct _LIBCPP_TEMPLATE_VIS tuple_element<1, pair<_T1, _T2> > {
196   using type _LIBCPP_NODEBUG = _T2;
197 };
198 
199 template <size_t _Ip>
200 struct __get_pair;
201 
202 template <>
203 struct __get_pair<0> {
204   template <class _T1, class _T2>
205   static _LIBCPP_HIDE_FROM_ABI _T1& get(pair<_T1, _T2>& __p) _NOEXCEPT {
206     return __p.first;
207   }
208 
209   template <class _T1, class _T2>
210   static _LIBCPP_HIDE_FROM_ABI const _T1& get(const pair<_T1, _T2>& __p) _NOEXCEPT {
211     return __p.first;
212   }
213 
214   template <class _T1, class _T2>
215   static _LIBCPP_HIDE_FROM_ABI _T1&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {
216     return std::forward<_T1>(__p.first);
217   }
218 
219   template <class _T1, class _T2>
220   static _LIBCPP_HIDE_FROM_ABI const _T1&& get(const pair<_T1, _T2>&& __p) _NOEXCEPT {
221     return std::forward<const _T1>(__p.first);
222   }
223 };
224 
225 template <>
226 struct __get_pair<1> {
227   template <class _T1, class _T2>
228   static _LIBCPP_HIDE_FROM_ABI _T2& get(pair<_T1, _T2>& __p) _NOEXCEPT {
229     return __p.second;
230   }
231 
232   template <class _T1, class _T2>
233   static _LIBCPP_HIDE_FROM_ABI const _T2& get(const pair<_T1, _T2>& __p) _NOEXCEPT {
234     return __p.second;
235   }
236 
237   template <class _T1, class _T2>
238   static _LIBCPP_HIDE_FROM_ABI _T2&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {
239     return std::forward<_T2>(__p.second);
240   }
241 
242   template <class _T1, class _T2>
243   static _LIBCPP_HIDE_FROM_ABI const _T2&& get(const pair<_T1, _T2>&& __p) _NOEXCEPT {
244     return std::forward<const _T2>(__p.second);
245   }
246 };
247 
248 template <size_t _Ip, class _T1, class _T2>
249 inline _LIBCPP_HIDE_FROM_ABI typename tuple_element<_Ip, pair<_T1, _T2> >::type& get(pair<_T1, _T2>& __p) _NOEXCEPT {
250   return __get_pair<_Ip>::get(__p);
251 }
252 
253 template <size_t _Ip, class _T1, class _T2>
254 inline _LIBCPP_HIDE_FROM_ABI const typename tuple_element<_Ip, pair<_T1, _T2> >::type&
255 get(const pair<_T1, _T2>& __p) _NOEXCEPT {
256   return __get_pair<_Ip>::get(__p);
257 }
258 
259 template <size_t _Ip, class _T1, class _T2>
260 inline _LIBCPP_HIDE_FROM_ABI typename tuple_element<_Ip, pair<_T1, _T2> >::type&& get(pair<_T1, _T2>&& __p) _NOEXCEPT {
261   return __get_pair<_Ip>::get(std::move(__p));
262 }
263 
264 template <size_t _Ip, class _T1, class _T2>
265 inline _LIBCPP_HIDE_FROM_ABI const typename tuple_element<_Ip, pair<_T1, _T2> >::type&&
266 get(const pair<_T1, _T2>&& __p) _NOEXCEPT {
267   return __get_pair<_Ip>::get(std::move(__p));
268 }
269 
270 _LIBCPP_END_NAMESPACE_STD
271 
272 _LIBCPP_POP_MACROS
273 
274 #endif // _LIBCPP___CXX03___UTILITY_PAIR_H
275