Phi
pair.hpp
1 #ifndef INCG_PHI_CORE_CONTAINER_ARRAY_HPP
2 #define INCG_PHI_CORE_CONTAINER_ARRAY_HPP
3 
4 #include "phi/phi_config.hpp"
5 
6 #if PHI_HAS_EXTENSION_PRAGMA_ONCE()
7 # pragma once
8 #endif
9 
10 #include "phi/compiler_support/constexpr.hpp"
11 #include "phi/compiler_support/nodiscard.hpp"
12 #include "phi/compiler_support/noexcept.hpp"
13 #include "phi/core/boolean.hpp"
14 #include "phi/core/forward.hpp"
15 #include "phi/type_traits/conditional.hpp"
16 #include "phi/type_traits/detail/nat.hpp"
17 #include "phi/type_traits/enable_if.hpp"
18 #include "phi/type_traits/is_constructible.hpp"
19 #include "phi/type_traits/is_convertible.hpp"
20 #include "phi/type_traits/is_copy_assignable.hpp"
21 #include "phi/type_traits/is_default_constructible.hpp"
22 #include "phi/type_traits/is_implicitly_default_constructible.hpp"
23 #include "phi/type_traits/is_move_assignable.hpp"
24 #include "phi/type_traits/is_nothrow_copy_assignable.hpp"
25 #include "phi/type_traits/is_nothrow_copy_constructible.hpp"
26 #include "phi/type_traits/is_nothrow_default_constructible.hpp"
27 #include "phi/type_traits/is_nothrow_move_assignable.hpp"
28 #include "phi/type_traits/is_nothrow_swappable.hpp"
29 #include "phi/type_traits/is_swappable.hpp"
30 
31 DETAIL_PHI_BEGIN_NAMESPACE()
32 
33 // 22.3.2 Class template pair, http://eel.is/c++draft/pairs#pair
34 template <typename FirstT, typename SecondT>
35 class pair
36 {
37  static PHI_CONSTEXPR_AND_CONST bool enable_implicit_default_constructor =
40 
41  static PHI_CONSTEXPR_AND_CONST bool enable_explicit_default_constructor =
43  !enable_implicit_default_constructor;
44 
45  static PHI_CONSTEXPR_AND_CONST bool enable_nothrow_default_constructor =
48 
49  static PHI_CONSTEXPR_AND_CONST bool enable_nothrow_copy_constructor =
52 
53  template <typename OtherFirstT, typename OtherSecondT>
54  static PHI_CONSTEXPR_AND_CONST bool enable_explicit_constructor =
59 
60  template <typename OtherFirstT, typename OtherSecondT>
61  static PHI_CONSTEXPR_AND_CONST bool enable_implicit_constructor =
66 
67 public:
69  using first_type = FirstT;
70  using second_type = SecondT;
71 
72  // Explicit default constructor
73  template <typename enable_if<enable_explicit_default_constructor>::type* = nullptr>
74  PHI_CONSTEXPR explicit pair() PHI_NOEXCEPT_EXPR(enable_nothrow_default_constructor)
75  : first{}
76  , second{}
77  {}
78 
79  // Implicit default constructor
80  template <typename enable_if<enable_implicit_default_constructor>::type* = nullptr>
81  PHI_CONSTEXPR pair() PHI_NOEXCEPT_EXPR(enable_nothrow_default_constructor)
82  : first{}
83  , second{}
84  {}
85 
86  // Default destructor
87  ~pair() = default;
88 
89  // Default copy constructor
90  pair(pair const&) = default;
91 
92  // Default move constructor
93  pair(pair&&) = default;
94 
95  // Explicit copy constructor
96  template <typename enable_if<
97  enable_explicit_constructor<const FirstT&, const SecondT&>>::type* = nullptr>
98  PHI_CONSTEXPR explicit pair(const FirstT& first_arg, const SecondT& second_arg)
99  PHI_NOEXCEPT_EXPR(enable_nothrow_copy_constructor)
100  : first{first_arg}
101  , second{second_arg}
102  {}
103 
104  // Implicit copy constructor
105  template <typename enable_if<
106  enable_implicit_constructor<const FirstT&, const SecondT&>>::type* = nullptr>
107  PHI_CONSTEXPR pair(const FirstT& first_arg, const SecondT& second_arg)
108  PHI_NOEXCEPT_EXPR(enable_nothrow_copy_constructor)
109  : first{first_arg}
110  , second{second_arg}
111  {}
112 
113  // http://wg21.link/P1951
114  // Explicit conversion constructor
115  template <typename OtherFirstT = FirstT, typename OtherSecondT = SecondT,
117  nullptr>
118  PHI_CONSTEXPR explicit pair(OtherFirstT&& other_first, OtherSecondT&& other_second)
121  : first{forward<OtherFirstT>(other_first)}
122  , second{forward<OtherSecondT>(other_second)}
123  {}
124 
125  // http://wg21.link/P1951
126  // Implicit conversion constructor
127  template <typename OtherFirstT = FirstT, typename OtherSecondT = SecondT,
129  nullptr>
130  PHI_CONSTEXPR pair(OtherFirstT&& other_first, OtherSecondT&& other_second)
133  : first{forward<OtherFirstT>(other_first)}
134  , second{forward<OtherSecondT>(other_second)}
135  {}
136 
137  // Explicit pair conversion constructor
138  template <typename OtherFirstT, typename OtherSecondT,
139  typename enable_if<enable_explicit_constructor<const OtherFirstT&,
140  const OtherSecondT&>>::type* = nullptr>
141  PHI_CONSTEXPR explicit pair(const pair<OtherFirstT, OtherSecondT>& other_pair)
144  : first{other_pair.first}
145  , second(other_pair.second)
146  {}
147 
148  // Implicit pair conversion constructor
149  template <typename OtherFirstT, typename OtherSecondT,
150  typename enable_if<enable_implicit_constructor<const OtherFirstT&,
151  const OtherSecondT&>>::type* = nullptr>
152  PHI_CONSTEXPR pair(const pair<OtherFirstT, SecondT>& other_pair)
155  : first{other_pair.first}
156  , second{other_pair.second}
157  {}
158 
159  // Explicit pair conversion move constructor
160  template <typename OtherFirstT, typename OtherSecondT,
162  nullptr>
163  PHI_CONSTEXPR explicit pair(pair<OtherFirstT, OtherSecondT>&& other_pair)
166  : first{forward<OtherFirstT>(other_pair.first)}
167  , second{forward<OtherSecondT>(other_pair.second)}
168  {}
169 
170  // Implicit pair conversion move constructor
171  template <typename OtherFirstT, typename OtherSecondT,
173  nullptr>
174  PHI_CONSTEXPR pair(pair<OtherFirstT, OtherSecondT>&& other_pair)
177  : first{forward<OtherFirstT>(other_pair.first)}
178  , second{forward<OtherSecondT>(other_pair.second)}
179  {}
180 
181  pair& operator=(const pair&) = default;
182 
183  pair& operator=(pair&&) = default;
184 
185  PHI_CONSTEXPR pair& operator=(typename conditional<is_copy_assignable<FirstT>::value &&
187  pair, nat>::type const& other_pair)
190  {
191  first = other_pair.first;
192  second = other_pair.second;
193 
194  return *this;
195  }
196 
197  PHI_CONSTEXPR pair& operator=(
200  pair, nat>::type&& other_pair)
203  {
204  first = forward<first_type>(other_pair.first);
205  second = forward<second_type>(other_pair.second);
206 
207  return *this;
208  }
209 
210  PHI_CONSTEXPR void swap(pair& other_pair) PHI_NOEXCEPT_EXPR(
212  {
213  using phi::swap;
214 
215  swap(first, other_pair.first);
216  swap(second, other_pair.second);
217  }
218 
219  PHI_CONSTEXPR void flip() PHI_NOEXCEPT_EXPR(
221  {
222  using phi::swap;
223 
224  swap(first, second);
225  }
226 
227  PHI_NODISCARD PHI_CONSTEXPR pair<SecondT, FirstT> as_flipped()
228  PHI_NOEXCEPT_EXPR(enable_nothrow_copy_constructor)
229  {
230  return pair<SecondT, FirstT>(second, first);
231  }
232 
233  FirstT first;
234  SecondT second;
235 };
236 
237 // 22.3.3 Specialized algorithms, https://eel.is/c++draft/pairs#spec
238 
239 template <typename FirstT, typename SecondT>
240 PHI_CONSTEXPR boolean operator==(const pair<FirstT, SecondT>& lhs, const pair<FirstT, SecondT>& rhs)
241 {
242  return lhs.first == rhs.first && lhs.second == rhs.second;
243 }
244 
245 template <typename FirstT, typename SecondT>
246 PHI_CONSTEXPR boolean operator!=(const pair<FirstT, SecondT>& lhs, const pair<FirstT, SecondT>& rhs)
247 {
248  return !(lhs == rhs);
249 }
250 
251 template <typename FirstT, typename SecondT>
252 PHI_CONSTEXPR boolean operator<(const pair<FirstT, SecondT>& lhs, const pair<FirstT, SecondT>& rhs)
253 {
254  return lhs.first < rhs.first || (!(rhs.first < lhs.first) && lhs.second < rhs.second);
255 }
256 
257 template <typename FirstT, typename SecondT>
258 PHI_CONSTEXPR boolean operator>(const pair<FirstT, SecondT>& lhs, const pair<FirstT, SecondT>& rhs)
259 {
260  return rhs < lhs;
261 }
262 
263 template <typename FirstT, typename SecondT>
264 PHI_CONSTEXPR boolean operator>=(const pair<FirstT, SecondT>& lhs, const pair<FirstT, SecondT>& rhs)
265 {
266  return !(lhs < rhs);
267 }
268 
269 template <typename FirstT, typename SecondT>
270 PHI_CONSTEXPR boolean operator<=(const pair<FirstT, SecondT>& lhs, const pair<FirstT, SecondT>& rhs)
271 {
272  return !(rhs < lhs);
273 }
274 
275 template <typename FirstT, typename SecondT>
276 PHI_CONSTEXPR
278  swap(pair<FirstT, SecondT>& lhs, pair<FirstT, SecondT>& rhs) PHI_NOEXCEPT_EXPR(
280 {
281  lhs.swap(rhs);
282 }
283 
284 template <typename FirstT, typename SecondT>
285 PHI_CONSTEXPR
287  void>::type
288  swap(const pair<FirstT, SecondT>& lhs, const pair<FirstT, SecondT>& rhs) PHI_NOEXCEPT_EXPR(
290 {
291  lhs.swap(rhs);
292 }
293 
294 template <typename FirstT, typename SecondT>
295 pair<FirstT, SecondT> make_pair(FirstT lhs, SecondT rhs)
296 {
297  return pair<FirstT, SecondT>(lhs, rhs);
298 }
299 
300 #if PHI_HAS_FEATURE_DEDUCTION_GUIDES()
301 template <typename FirstTypeT, typename SecondTypeT>
302 pair(FirstTypeT, SecondTypeT) -> pair<FirstTypeT, SecondTypeT>;
303 #endif
304 
305 DETAIL_PHI_END_NAMESPACE()
306 
307 #endif // INCG_PHI_CORE_CONTAINER_ARRAY_HPP
Definition: is_nothrow_copy_constructible.hpp:26
Definition: is_nothrow_swappable.hpp:21
Definition: is_nothrow_move_assignable.hpp:20
Definition: conditional.hpp:13
Definition: is_default_constructible.hpp:91
Definition: is_copy_assignable.hpp:20
Definition: pair.hpp:35
Definition: is_implicitly_default_constructible.hpp:34
Definition: nat.hpp:12
Definition: is_convertible.hpp:217
Definition: is_nothrow_copy_assignable.hpp:20
Definition: enable_if.hpp:15
Definition: is_constructible.hpp:73
Definition: is_nothrow_default_constructible.hpp:21
Definition: is_nothrow_constructible.hpp:160
Definition: is_move_assignable.hpp:20
Definition: is_swappable.hpp:21
Definition: is_convertible.hpp:227