source: mainline/uspace/lib/cpp/include/__bits/utility/utility.hpp@ 8624d1f

Last change on this file since 8624d1f was b57ba05, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 3 years ago

Update headers in C++ files

  • Property mode set to 100644
File size: 10.6 KB
Line 
1/*
2 * SPDX-FileCopyrightText: 2018 Jaroslav Jindrak
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef LIBCPP_BITS_UTILITY
8#define LIBCPP_BITS_UTILITY
9
10#include <__bits/type_transformation.hpp>
11#include <__bits/utility/forward_move.hpp>
12#include <cstdint>
13#include <type_traits>
14
15namespace std
16{
17 /**
18 * 20.2.1, operators:
19 */
20
21 namespace rel_ops
22 {
23 template<typename T>
24 bool operator!=(const T& lhs, const T& rhs)
25 {
26 return !(lhs == rhs);
27 }
28
29 template<typename T>
30 bool operator>(const T& lhs, const T& rhs)
31 {
32 return (rhs < lhs);
33 }
34
35 template<typename T>
36 bool operator<=(const T& lhs, const T& rhs)
37 {
38 return !(rhs < lhs);
39 }
40
41 template<typename T>
42 bool operator>=(const T& lhs, const T& rhs)
43 {
44 return !(lhs < rhs);
45 }
46 }
47
48 /**
49 * 20.2.2, swap:
50 */
51
52 template<class T>
53 void swap(T& x, T& y)
54 /* noexcept(is_nothrow_move_constructible<T>::value && */
55 /* is_nothrow_move_assignable<T>::value) */
56 {
57 T tmp{move(x)};
58 x = move(y);
59 y = move(tmp);
60 }
61
62 template<class F1, class F2>
63 F2 swap_ranges(F1, F1, F2);
64
65 template<class T, size_t N>
66 void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(swap(*a, *b)))
67 {
68 swap_ranges(a, a + N, b);
69 }
70
71 /**
72 * 20.2.3, exchange:
73 */
74
75 template<class T, class U = T>
76 T exchange(T& obj, U&& new_val)
77 {
78 T old_val = move(obj);
79 obj = forward<U>(new_val);
80
81 return old_val;
82 }
83
84 /**
85 * 20.5.2, class template integer_sequence:
86 */
87
88 template<class T, T... Is>
89 struct integer_sequence
90 {
91 using value_type = T;
92
93 static constexpr size_t size() noexcept
94 {
95 return sizeof...(Is);
96 }
97
98 using next = integer_sequence<T, Is..., sizeof...(Is)>;
99 };
100
101 template<std::size_t... Is>
102 using index_sequence = integer_sequence<std::size_t, Is...>;
103
104 /**
105 * 20.5.3, alias template make_integer_sequence:
106 */
107
108 namespace aux
109 {
110 template<class T, uintmax_t N>
111 struct make_integer_sequence
112 {
113 /**
114 * Recursive to the bottom case below, appends sizeof...(Is) in
115 * every next "call", building the sequence.
116 */
117 using type = typename make_integer_sequence<T, N - 1>::type::next;
118 };
119
120 template<class T>
121 struct make_integer_sequence<T, std::uintmax_t(0)>
122 {
123 using type = integer_sequence<T>;
124 };
125 }
126
127
128 /**
129 * Problem: We can't specialize the N parameter because it is a value parameter
130 * depending on a type parameter.
131 * Solution: According to the standard: if N is negative, the program is ill-formed,
132 * so we just recast it to uintmax_t :)
133 */
134 template<class T, T N>
135 using make_integer_sequence = typename aux::make_integer_sequence<T, std::uintmax_t(N)>::type;
136
137 template<size_t N>
138 using make_index_sequence = make_integer_sequence<std::size_t, N>;
139
140 /**
141 * 20.3, pairs:
142 */
143
144 template<size_t, class>
145 class tuple_element;
146
147 template<size_t I, class T>
148 using tuple_element_t = typename tuple_element<I, T>::type;
149
150 template<class...>
151 class tuple;
152
153 template<size_t I, class... Ts>
154 constexpr tuple_element_t<I, tuple<Ts...>>&& get(tuple<Ts...>&&) noexcept;
155
156 namespace aux
157 {
158 template<class T, class... Args, size_t... Is>
159 T from_tuple(tuple<Args...>&& tpl, index_sequence<Is...>)
160 {
161 return T{get<Is>(move(tpl))...};
162 }
163
164 template<class T, class... Args>
165 T from_tuple(tuple<Args...>&& tpl)
166 {
167 return from_tuple<T>(move(tpl), make_index_sequence<sizeof...(Args)>{});
168 }
169 }
170
171 struct piecewise_construct_t
172 {
173 explicit piecewise_construct_t() = default;
174 };
175
176 inline constexpr piecewise_construct_t piecewise_construct{};
177
178 template<typename T1, typename T2>
179 struct pair
180 {
181 using first_type = T1;
182 using second_type = T2;
183
184 T1 first;
185 T2 second;
186
187 pair(const pair&) = default;
188 pair(pair&&) = default;
189
190 constexpr pair()
191 : first{}, second{}
192 { /* DUMMY BODY */ }
193
194 constexpr pair(const T1& x, const T2& y)
195 : first{x}, second{y}
196 { /* DUMMY BODY */ }
197
198 template<typename U, typename V>
199 constexpr pair(U&& x, V&& y)
200 : first(x), second(y)
201 { /* DUMMY BODY */ }
202
203 template<typename U, typename V>
204 constexpr pair(const pair<U, V>& other)
205 : first(other.first), second(other.second)
206 { /* DUMMY BODY */ }
207
208 template<typename U, typename V>
209 constexpr pair(pair<U, V>&& other)
210 : first(forward<first_type>(other.first)),
211 second(forward<second_type>(other.second))
212 { /* DUMMY BODY */ }
213
214 template<class... Args1, class... Args2>
215 pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args)
216 : first{aux::from_tuple<first_type>(move(first_args))},
217 second{aux::from_tuple<second_type>(move(second_args))}
218 { /* DUMMY BODY */ }
219
220 pair& operator=(const pair& other)
221 {
222 first = other.first;
223 second = other.second;
224
225 return *this;
226 }
227
228 template<typename U, typename V>
229 pair& operator=(const pair<U, V>& other)
230 {
231 first = other.first;
232 second = other.second;
233
234 return *this;
235 }
236
237 pair& operator=(pair&& other) noexcept
238 {
239 first = forward<first_type>(other.first);
240 second = forward<second_type>(other.second);
241
242 return *this;
243 }
244
245 template<typename U, typename V>
246 pair& operator=(pair<U, V>&& other)
247 {
248 first = forward<first_type>(other.first);
249 second = forward<second_type>(other.second);
250
251 return *this;
252 }
253
254 void swap(pair& other) noexcept(
255 noexcept(std::swap(first, other.first)) &&
256 noexcept(std::swap(second, other.second))
257 )
258 {
259 std::swap(first, other.first);
260 std::swap(second, other.second);
261 }
262 };
263
264 /**
265 * 20.3.3, specialized algorithms:
266 */
267
268 template<class T1, class T2>
269 constexpr bool operator==(const pair<T1, T2>& lhs,
270 const pair<T1, T2>& rhs)
271 {
272 return lhs.first == rhs.first && lhs.second == rhs.second;
273 }
274
275 template<class T1, class T2>
276 constexpr bool operator<(const pair<T1, T2>& lhs,
277 const pair<T1, T2>& rhs)
278 {
279 return lhs.first < rhs.first ||
280 (!(rhs.first < lhs.first) && lhs.second < rhs.second);
281 }
282
283 template<class T1, class T2>
284 constexpr bool operator!=(const pair<T1, T2>& lhs,
285 const pair<T1, T2>& rhs)
286 {
287 return !(lhs == rhs);
288 }
289
290 template<class T1, class T2>
291 constexpr bool operator>(const pair<T1, T2>& lhs,
292 const pair<T1, T2>& rhs)
293 {
294 return rhs < lhs;
295 }
296
297 template<class T1, class T2>
298 constexpr bool operator>=(const pair<T1, T2>& lhs,
299 const pair<T1, T2>& rhs)
300 {
301 return !(lhs < rhs);
302 }
303
304 template<class T1, class T2>
305 constexpr bool operator<=(const pair<T1, T2>& lhs,
306 const pair<T1, T2>& rhs)
307 {
308 return !(rhs < lhs);
309 }
310
311 template<class T1, class T2>
312 constexpr void swap(pair<T1, T2>& lhs, pair<T1, T2>& rhs)
313 noexcept(noexcept(lhs.swap(rhs)))
314 {
315 lhs.swap(rhs);
316 }
317
318 template<class T1, class T2>
319 constexpr auto make_pair(T1&& t1, T2&& t2)
320 {
321 return pair<
322 aux::transform_tuple_types_t<T1>,
323 aux::transform_tuple_types_t<T2>
324 >{
325 forward<T1>(t1), forward<T2>(t2)
326 };
327 }
328
329 /**
330 * 20.3.4, tuple-like access to pair:
331 */
332
333 template<class>
334 struct tuple_size;
335
336 template<class T1, class T2>
337 struct tuple_size<pair<T1, T2>>
338 : integral_constant<size_t, 2>
339 { /* DUMMY BODY */ };
340
341 template<size_t, class>
342 struct tuple_element;
343
344 template<class T1, class T2>
345 struct tuple_element<0, pair<T1, T2>>
346 : aux::type_is<T1>
347 { /* DUMMY BODY */ };
348
349 template<class T1, class T2>
350 struct tuple_element<1, pair<T1, T2>>
351 : aux::type_is<T2>
352 { /* DUMMY BODY */ };
353
354 template<size_t I, class T>
355 using tuple_element_t = typename tuple_element<I, T>::type;
356
357 template<size_t I, class T1, class T2>
358 constexpr tuple_element_t<I, pair<T1, T2>>&
359 get(pair<T1, T2>& p) noexcept
360 {
361 if constexpr (I == 0)
362 return p.first;
363 else
364 return p.second;
365 }
366
367 template<size_t I, class T1, class T2>
368 constexpr const tuple_element_t<I, pair<T1, T2>>&
369 get(const pair<T1, T2>& p) noexcept
370 {
371 if constexpr (I == 0)
372 return p.first;
373 else
374 return p.second;
375 }
376
377 template<size_t I, class T1, class T2>
378 constexpr tuple_element_t<I, pair<T1, T2>>&&
379 get(pair<T1, T2>&& p) noexcept
380 {
381 if constexpr (I == 0)
382 return forward<T1>(p.first);
383 else
384 return forward<T2>(p.second);
385 }
386
387 template<class T, class U>
388 constexpr T& get(pair<T, U>& p) noexcept
389 {
390 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
391
392 return get<0>(p);
393 }
394
395 template<class T, class U>
396 constexpr const T& get(const pair<T, U>& p) noexcept
397 {
398 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
399
400 return get<0>(p);
401 }
402
403 template<class T, class U>
404 constexpr T&& get(pair<T, U>&& p) noexcept
405 {
406 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
407
408 return get<0>(move(p));
409 }
410
411 template<class T, class U>
412 constexpr T& get(pair<U, T>& p) noexcept
413 {
414 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
415
416 return get<1>(p);
417 }
418
419 template<class T, class U>
420 constexpr const T& get(const pair<U, T>& p) noexcept
421 {
422 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
423
424 return get<1>(p);
425 }
426
427 template<class T, class U>
428 constexpr T&& get(pair<U, T>&& p) noexcept
429 {
430 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
431
432 return get<1>(move(p));
433 }
434}
435
436#endif
Note: See TracBrowser for help on using the repository browser.