source: mainline/uspace/lib/cpp/include/impl/utility.hpp@ 13f7525

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 13f7525 was aa0fa86a, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: added pair::pair(piecewise_construct_t, …), but had to temporarily remove templated tuple constructor which needs is_convertible etc on variadic types

  • Property mode set to 100644
File size: 12.0 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_UTILITY
30#define LIBCPP_UTILITY
31
32#include <cstdint>
33#include <internal/type_transformation.hpp>
34#include <type_traits>
35
36namespace std
37{
38 /**
39 * 20.2.1, operators:
40 */
41
42 namespace rel_ops
43 {
44 template<typename T>
45 bool operator!=(const T& lhs, const T& rhs)
46 {
47 return !(lhs == rhs);
48 }
49
50 template<typename T>
51 bool operator>(const T& lhs, const T& rhs)
52 {
53 return (rhs < lhs);
54 }
55
56 template<typename T>
57 bool operator<=(const T& lhs, const T& rhs)
58 {
59 return !(rhs < lhs);
60 }
61
62 template<typename T>
63 bool operator>=(const T& lhs, const T& rhs)
64 {
65 return !(lhs < rhs);
66 }
67 }
68
69 /**
70 * 20.2.4, forward/move helpers:
71 */
72
73 template<class T>
74 constexpr T&& forward(remove_reference_t<T>& t) noexcept
75 {
76 return static_cast<T&&>(t);
77 }
78
79 template<class T>
80 constexpr T&& forward(remove_reference_t<T>&& t) noexcept
81 {
82 return static_cast<T&&>(t);
83 }
84
85 template<class T>
86 constexpr remove_reference_t<T>&& move(T&& t) noexcept
87 {
88 return static_cast<remove_reference_t<T>&&>(t);
89 }
90
91 /**
92 * 20.2.2, swap:
93 */
94
95 template<class T>
96 void swap(T& x, T& y)
97 /* noexcept(is_nothrow_move_constructible<T>::value && */
98 /* is_nothrow_move_assignable<T>::value) */
99 {
100 T tmp{move(x)};
101 x = move(y);
102 y = move(tmp);
103 }
104
105 template<class F1, class F2>
106 F2 swap_ranges(F1, F1, F2);
107
108 template<class T, size_t N>
109 void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(swap(*a, *b)))
110 {
111 swap_ranges(a, a + N, b);
112 }
113
114 /**
115 * 20.2.3, exchange:
116 */
117
118 template<class T, class U = T>
119 T exchange(T& obj, U&& new_val)
120 {
121 T old_val = move(obj);
122 obj = forward<U>(new_val);
123
124 return old_val;
125 }
126
127 /**
128 * 20.2.5, function template declval:
129 * Note: This function only needs declaration, not
130 * implementation.
131 */
132
133 template<class T>
134 add_rvalue_reference_t<T> declval() noexcept;
135
136 /**
137 * 20.5.2, class template integer_sequence:
138 */
139
140 template<class T, T... Is>
141 struct integer_sequence
142 {
143 using value_type = T;
144
145 static constexpr size_t size() noexcept
146 {
147 return sizeof...(Is);
148 }
149
150 using next = integer_sequence<T, Is..., sizeof...(Is)>;
151 };
152
153 template<std::size_t... Is>
154 using index_sequence = integer_sequence<std::size_t, Is...>;
155
156 /**
157 * 20.5.3, alias template make_integer_sequence:
158 */
159
160 namespace aux
161 {
162 template<class T, uintmax_t N>
163 struct make_integer_sequence
164 {
165 /**
166 * Recursive to the bottom case below, appends sizeof...(Is) in
167 * every next "call", building the sequence.
168 */
169 using type = typename make_integer_sequence<T, N - 1>::type::next;
170 };
171
172 template<class T>
173 struct make_integer_sequence<T, std::uintmax_t(0)>
174 {
175 using type = integer_sequence<T>;
176 };
177 }
178
179
180 /**
181 * Problem: We can't specialize the N parameter because it is a value parameter
182 * depending on a type parameter.
183 * Solution: According to the standard: if N is negative, the program is ill-formed,
184 * so we just recast it to uintmax_t :)
185 */
186 template<class T, T N>
187 using make_integer_sequence = typename aux::make_integer_sequence<T, std::uintmax_t(N)>::type;
188
189 template<size_t N>
190 using make_index_sequence = make_integer_sequence<std::size_t, N>;
191
192 /**
193 * 20.3, pairs:
194 */
195
196 template<size_t, class>
197 class tuple_element;
198
199 template<size_t I, class T>
200 using tuple_element_t = typename tuple_element<I, T>::type;
201
202 template<class...>
203 class tuple;
204
205 template<size_t I, class... Ts>
206 constexpr tuple_element_t<I, tuple<Ts...>>&& get(tuple<Ts...>&&) noexcept;
207
208 namespace aux
209 {
210 template<class T, class... Args, size_t... Is>
211 T from_tuple(tuple<Args...>&& tpl, index_sequence<Is...>)
212 {
213 return T{get<Is>(move(tpl))...};
214 }
215
216 template<class T, class... Args>
217 T from_tuple(tuple<Args...>&& tpl)
218 {
219 return from_tuple<T>(move(tpl), make_index_sequence<sizeof...(Args)>{});
220 }
221 }
222
223 struct piecewise_construct_t
224 {
225 explicit piecewise_construct_t() = default;
226 };
227
228 inline constexpr piecewise_construct_t piecewise_construct{};
229
230 template<typename T1, typename T2>
231 struct pair
232 {
233 using first_type = T1;
234 using second_type = T2;
235
236 T1 first;
237 T2 second;
238
239 pair(const pair&) = default;
240 pair(pair&&) = default;
241
242 constexpr pair()
243 : first{}, second{}
244 { /* DUMMY BODY */ }
245
246 constexpr pair(const T1& x, const T2& y)
247 : first{x}, second{y}
248 { /* DUMMY BODY */ }
249
250 template<typename U, typename V>
251 constexpr pair(U&& x, V&& y)
252 : first(x), second(y)
253 { /* DUMMY BODY */ }
254
255 template<typename U, typename V>
256 constexpr pair(const pair<U, V>& other)
257 : first(other.first), second(other.second)
258 { /* DUMMY BODY */ }
259
260 template<typename U, typename V>
261 constexpr pair(pair<U, V>&& other)
262 : first(forward<first_type>(other.first)),
263 second(forward<second_type>(other.second))
264 { /* DUMMY BODY */ }
265
266 template<class... Args1, class... Args2>
267 pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args)
268 : first{aux::from_tuple<first_type>(move(first_args))},
269 second{aux::from_tuple<second_type>(move(second_args))}
270 { /* DUMMY BODY */ }
271
272 pair& operator=(const pair& other)
273 {
274 first = other.first;
275 second = other.second;
276
277 return *this;
278 }
279
280 template<typename U, typename V>
281 pair& operator=(const pair<U, V>& other)
282 {
283 first = other.first;
284 second = other.second;
285
286 return *this;
287 }
288
289 pair& operator=(pair&& other) noexcept
290 {
291 first = forward<first_type>(other.first);
292 second = forward<second_type>(other.second);
293
294 return *this;
295 }
296 };
297
298 /**
299 * 20.3.3, specialized algorithms:
300 */
301
302 template<class T1, class T2>
303 constexpr bool operator==(const pair<T1, T2>& lhs,
304 const pair<T1, T2>& rhs)
305 {
306 return lhs.first == rhs.first && lhs.second == rhs.second;
307 }
308
309 template<class T1, class T2>
310 constexpr bool operator<(const pair<T1, T2>& lhs,
311 const pair<T1, T2>& rhs)
312 {
313 return lhs.first < rhs.first ||
314 (!(rhs.first < lhs.first) && lhs.second < rhs.second);
315 }
316
317 template<class T1, class T2>
318 constexpr bool operator!=(const pair<T1, T2>& lhs,
319 const pair<T1, T2>& rhs)
320 {
321 return !(lhs == rhs);
322 }
323
324 template<class T1, class T2>
325 constexpr bool operator>(const pair<T1, T2>& lhs,
326 const pair<T1, T2>& rhs)
327 {
328 return rhs < lhs;
329 }
330
331 template<class T1, class T2>
332 constexpr bool operator>=(const pair<T1, T2>& lhs,
333 const pair<T1, T2>& rhs)
334 {
335 return !(lhs < rhs);
336 }
337
338 template<class T1, class T2>
339 constexpr bool operator<=(const pair<T1, T2>& lhs,
340 const pair<T1, T2>& rhs)
341 {
342 return !(rhs < lhs);
343 }
344
345 template<class T1, class T2>
346 constexpr void swap(pair<T1, T2>& lhs, pair<T1, T2>& rhs)
347 noexcept(noexcept(lhs.swap(rhs)))
348 {
349 lhs.swap(rhs);
350 }
351
352 template<class T1, class T2>
353 constexpr auto make_pair(T1&& t1, T2&& t2)
354 {
355 return pair<
356 aux::transform_tuple_types_t<T1>,
357 aux::transform_tuple_types_t<T2>
358 >{
359 forward<T1>(t1), forward<T2>(t2)
360 };
361 }
362
363 /**
364 * 20.3.4, tuple-like access to pair:
365 */
366
367 template<class>
368 struct tuple_size;
369
370 template<class T1, class T2>
371 struct tuple_size<pair<T1, T2>>
372 : integral_constant<size_t, 2>
373 { /* DUMMY BODY */ };
374
375 template<size_t, class>
376 struct tuple_element;
377
378 template<class T1, class T2>
379 struct tuple_element<0, pair<T1, T2>>
380 : aux::type_is<T1>
381 { /* DUMMY BODY */ };
382
383 template<class T1, class T2>
384 struct tuple_element<1, pair<T1, T2>>
385 : aux::type_is<T2>
386 { /* DUMMY BODY */ };
387
388 template<size_t I, class T>
389 using tuple_element_t = typename tuple_element<I, T>::type;
390
391 template<size_t I, class T1, class T2>
392 constexpr tuple_element_t<I, pair<T1, T2>>&
393 get(pair<T1, T2>& p) noexcept
394 {
395 if constexpr (I == 0)
396 return p.first;
397 else
398 return p.second;
399 }
400
401 template<size_t I, class T1, class T2>
402 constexpr const tuple_element_t<I, pair<T1, T2>>&
403 get(const pair<T1, T2>& p) noexcept
404 {
405 if constexpr (I == 0)
406 return p.first;
407 else
408 return p.second;
409 }
410
411 template<size_t I, class T1, class T2>
412 constexpr tuple_element_t<I, pair<T1, T2>>&&
413 get(pair<T1, T2>&& p) noexcept
414 {
415 if constexpr (I == 0)
416 return forward<T1>(p.first);
417 else
418 return forward<T2>(p.second);
419 }
420
421 template<class T, class U>
422 constexpr T& get(pair<T, U>& p) noexcept
423 {
424 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
425
426 return get<0>(p);
427 }
428
429 template<class T, class U>
430 constexpr const T& get(const pair<T, U>& p) noexcept
431 {
432 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
433
434 return get<0>(p);
435 }
436
437 template<class T, class U>
438 constexpr T&& get(pair<T, U>&& p) noexcept
439 {
440 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
441
442 return get<0>(move(p));
443 }
444
445 template<class T, class U>
446 constexpr T& get(pair<U, T>& p) noexcept
447 {
448 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
449
450 return get<1>(p);
451 }
452
453 template<class T, class U>
454 constexpr const T& get(const pair<U, T>& p) noexcept
455 {
456 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
457
458 return get<1>(p);
459 }
460
461 template<class T, class U>
462 constexpr T&& get(pair<U, T>&& p) noexcept
463 {
464 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
465
466 return get<1>(move(p));
467 }
468}
469
470#endif
Note: See TracBrowser for help on using the repository browser.