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

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

cpp: added missing swap for arrays

  • Property mode set to 100644
File size: 11.2 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.3, pairs:
138 */
139
140 struct piecewise_construct_t
141 {
142 explicit piecewise_construct_t() = default;
143 };
144
145 template<typename T1, typename T2>
146 struct pair
147 {
148 using first_type = T1;
149 using second_type = T2;
150
151 T1 first;
152 T2 second;
153
154 pair(const pair&) = default;
155 pair(pair&&) = default;
156
157 constexpr pair()
158 : first{}, second{}
159 { /* DUMMY BODY */ }
160
161 constexpr pair(const T1& x, const T2& y)
162 : first{x}, second{y}
163 { /* DUMMY BODY */ }
164
165 template<typename U, typename V>
166 constexpr pair(U&& x, V&& y)
167 : first(x), second(y)
168 { /* DUMMY BODY */ }
169
170 template<typename U, typename V>
171 constexpr pair(const pair<U, V>& other)
172 : first(other.first), second(other.second)
173 { /* DUMMY BODY */ }
174
175 template<typename U, typename V>
176 constexpr pair(pair<U, V>&& other)
177 : first(forward<first_type>(other.first)),
178 second(forward<second_type>(other.second))
179 { /* DUMMY BODY */ }
180
181 /* TODO: need tuple, piecewise_construct_t
182 template<class... Args1, class... Args2>
183 pair(piecewise_construct_t, tuple<Args1...> first_args, tuple<Args2...> second_args)
184 {
185 // TODO:
186 }
187 */
188
189 pair& operator=(const pair& other)
190 {
191 first = other.first;
192 second = other.second;
193
194 return *this;
195 }
196
197 template<typename U, typename V>
198 pair& operator=(const pair<U, V>& other)
199 {
200 first = other.first;
201 second = other.second;
202
203 return *this;
204 }
205
206 pair& operator=(pair&& other) noexcept
207 {
208 first = forward<first_type>(other.first);
209 second = forward<second_type>(other.second);
210
211 return *this;
212 }
213 };
214
215 /**
216 * 20.3.3, specialized algorithms:
217 */
218
219 template<class T1, class T2>
220 constexpr bool operator==(const pair<T1, T2>& lhs,
221 const pair<T1, T2>& rhs)
222 {
223 return lhs.first == rhs.first && lhs.second == rhs.second;
224 }
225
226 template<class T1, class T2>
227 constexpr bool operator<(const pair<T1, T2>& lhs,
228 const pair<T1, T2>& rhs)
229 {
230 return lhs.first < rhs.first ||
231 (!(rhs.first < lhs.first) && lhs.second < rhs.second);
232 }
233
234 template<class T1, class T2>
235 constexpr bool operator!=(const pair<T1, T2>& lhs,
236 const pair<T1, T2>& rhs)
237 {
238 return !(lhs == rhs);
239 }
240
241 template<class T1, class T2>
242 constexpr bool operator>(const pair<T1, T2>& lhs,
243 const pair<T1, T2>& rhs)
244 {
245 return rhs < lhs;
246 }
247
248 template<class T1, class T2>
249 constexpr bool operator>=(const pair<T1, T2>& lhs,
250 const pair<T1, T2>& rhs)
251 {
252 return !(lhs < rhs);
253 }
254
255 template<class T1, class T2>
256 constexpr bool operator<=(const pair<T1, T2>& lhs,
257 const pair<T1, T2>& rhs)
258 {
259 return !(rhs < lhs);
260 }
261
262 template<class T1, class T2>
263 constexpr void swap(pair<T1, T2>& lhs, pair<T1, T2>& rhs)
264 noexcept(noexcept(lhs.swap(rhs)))
265 {
266 lhs.swap(rhs);
267 }
268
269 template<class T1, class T2>
270 constexpr auto make_pair(T1&& t1, T2&& t2)
271 {
272 return pair<
273 aux::transform_tuple_types_t<T1>,
274 aux::transform_tuple_types_t<T2>
275 >{
276 forward<T1>(t1), forward<T2>(t2)
277 };
278 }
279
280 /**
281 * 20.3.4, tuple-like access to pair:
282 */
283
284 template<class>
285 struct tuple_size;
286
287 template<class T1, class T2>
288 struct tuple_size<pair<T1, T2>>
289 : integral_constant<size_t, 2>
290 { /* DUMMY BODY */ };
291
292 template<size_t, class>
293 struct tuple_element;
294
295 template<class T1, class T2>
296 struct tuple_element<0, pair<T1, T2>>
297 : aux::type_is<T1>
298 { /* DUMMY BODY */ };
299
300 template<class T1, class T2>
301 struct tuple_element<1, pair<T1, T2>>
302 : aux::type_is<T2>
303 { /* DUMMY BODY */ };
304
305 template<size_t I, class T>
306 using tuple_element_t = typename tuple_element<I, T>::type;
307
308 template<size_t I, class T1, class T2>
309 constexpr tuple_element_t<I, pair<T1, T2>>&
310 get(pair<T1, T2>& p) noexcept
311 {
312 if constexpr (I == 0)
313 return p.first;
314 else
315 return p.second;
316 }
317
318 template<size_t I, class T1, class T2>
319 constexpr const tuple_element_t<I, pair<T1, T2>>&
320 get(const pair<T1, T2>& p) noexcept
321 {
322 if constexpr (I == 0)
323 return p.first;
324 else
325 return p.second;
326 }
327
328 template<size_t I, class T1, class T2>
329 constexpr tuple_element_t<I, pair<T1, T2>>&&
330 get(pair<T1, T2>&& p) noexcept
331 {
332 if constexpr (I == 0)
333 return forward<T1>(p.first);
334 else
335 return forward<T2>(p.second);
336 }
337
338 template<class T, class U>
339 constexpr T& get(pair<T, U>& p) noexcept
340 {
341 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
342
343 return get<0>(p);
344 }
345
346 template<class T, class U>
347 constexpr const T& get(const pair<T, U>& p) noexcept
348 {
349 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
350
351 return get<0>(p);
352 }
353
354 template<class T, class U>
355 constexpr T&& get(pair<T, U>&& p) noexcept
356 {
357 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
358
359 return get<0>(move(p));
360 }
361
362 template<class T, class U>
363 constexpr T& get(pair<U, T>& p) noexcept
364 {
365 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
366
367 return get<1>(p);
368 }
369
370 template<class T, class U>
371 constexpr const T& get(const pair<U, T>& p) noexcept
372 {
373 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
374
375 return get<1>(p);
376 }
377
378 template<class T, class U>
379 constexpr T&& get(pair<U, T>&& p) noexcept
380 {
381 static_assert(!is_same_v<T, U>, "get(pair) requires distinct types");
382
383 return get<1>(move(p));
384 }
385
386 /**
387 * 20.5.2, class template integer_sequence:
388 */
389
390 template<class T, T... Is>
391 struct integer_sequence
392 {
393 using value_type = T;
394
395 static constexpr size_t size() noexcept
396 {
397 return sizeof...(Is);
398 }
399
400 using next = integer_sequence<T, Is..., sizeof...(Is)>;
401 };
402
403 template<std::size_t... Is>
404 using index_sequence = integer_sequence<std::size_t, Is...>;
405
406 /**
407 * 20.5.3, alias template make_integer_sequence:
408 */
409
410 namespace aux
411 {
412 template<class T, uintmax_t N>
413 struct make_integer_sequence
414 {
415 /**
416 * Recursive to the bottom case below, appends sizeof...(Is) in
417 * every next "call", building the sequence.
418 */
419 using type = typename make_integer_sequence<T, N - 1>::type::next;
420 };
421
422 template<class T>
423 struct make_integer_sequence<T, std::uintmax_t(0)>
424 {
425 using type = integer_sequence<T>;
426 };
427 }
428
429
430 /**
431 * Problem: We can't specialize the N parameter because it is a value parameter
432 * depending on a type parameter.
433 * Solution: According to the standard: if N is negative, the program is ill-formed,
434 * so we just recast it to uintmax_t :)
435 */
436 template<class T, T N>
437 using make_integer_sequence = typename aux::make_integer_sequence<T, std::uintmax_t(N)>::type;
438
439 template<size_t N>
440 using make_index_sequence = make_integer_sequence<std::size_t, N>;
441}
442
443#endif
Note: See TracBrowser for help on using the repository browser.