source: mainline/uspace/lib/cpp/include/impl/functional.hpp@ 82fd245

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

cpp: added <functional> declaration and implementations of invoke and operations

  • Property mode set to 100644
File size: 18.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_FUNCTIONAL
30#define LIBCPP_FUNCTIONAL
31
32#include <type_traits>
33
34namespace std
35{
36 namespace aux
37 {
38 /**
39 * 20.9.2, requirements:
40 */
41 template<class R, class T, class T1, class... Ts>
42 decltype(auto) invoke(R T::* f, T1&& t1, Args&&... args)
43 {
44 if constexpr (is_member_function_pointer_v<decltype(f)>)
45 {
46 if constexpr (is_base_of_v<T, remove_reference_t<T1>>)
47 // (1.1)
48 return (t1.*f)(forward<Args>(args)...);
49 else
50 // (1.2)
51 return ((*t1).*f)(forward<Args>(args)...);
52 }
53 else if (is_member_object_pointer_v<decltype(f)> && sizeof...(args) == 0)
54 {
55 /**
56 * Note: Standard requires to N be equal to 1, but we take t1 directly
57 * so we need sizeof...(args) to be 0.
58 */
59 if constexpr (is_base_of_v<T, remove_reference_t<T1>>)
60 // (1.3)
61 return t1.*f;
62 else
63 // (1.4)
64 return (*t1).*f;
65 }
66 static_assert(false, "invalid invoke");
67 }
68
69 template<class F, class... Args>
70 decltype(auto) invoke(F&& f, Args&&... args)
71 {
72 // (1.5)
73 return f(forward<Args>(args)...);
74 }
75 }
76
77 /**
78 * 20.9.3, invoke:
79 */
80
81 template<class F, class... Args>
82 result_of_t<F&&(Args&&...)> invoke(F&& f, Args&&... args)
83 {
84 return aux::invoke(forward<F>(f)(forward<Args>(args)...));
85 }
86
87 /**
88 * 20.9.4, reference_wrapper:
89 */
90
91 template<class T>
92 class reference_wrapper;
93
94 template<class T>
95 reference_wrapper<T> ref(T& t) noexcept;
96
97 template<class T>
98 reference_wrapper<const T> cref(const T& t) noexcept;
99
100 template<class T>
101 void ref(const T&&) = delete;
102
103 template<class T>
104 void cref(const T&&) = delete;
105
106 template<class T>
107 reference_wrapper<T> ref(reference_wrapper<T> ref) noexcept;
108
109 template<class T>
110 reference_wrapper<const T> cref(reference_wrapper<T> ref) noexcept;
111
112 /**
113 * 20.9.5, arithmetic operations:
114 */
115
116 template<class T = void>
117 struct plus
118 {
119 constexpr T operator()(const T& lhs, const T& rhs) const
120 {
121 return lhs + rhs;
122 }
123
124 using first_argument_type = T;
125 using second_argument_type = T;
126 using result_type = T;
127 };
128
129 template<class T = void>
130 struct minus
131 {
132 constexpr T operator()(const T& lhs, const T& rhs) const
133 {
134 return lhs - rhs;
135 }
136
137 using first_argument_type = T;
138 using second_argument_type = T;
139 using result_type = T;
140 };
141
142 template<class T = void>
143 struct multiplies
144 {
145 constexpr T operator()(const T& lhs, const T& rhs) const
146 {
147 return lhs * rhs;
148 }
149
150 using first_argument_type = T;
151 using second_argument_type = T;
152 using result_type = T;
153 };
154
155 template<class T = void>
156 struct divides
157 {
158 constexpr T operator()(const T& lhs, const T& rhs) const
159 {
160 return lhs / rhs;
161 }
162
163 using first_argument_type = T;
164 using second_argument_type = T;
165 using result_type = T;
166 };
167
168 template<class T = void>
169 struct modulus
170 {
171 constexpr T operator()(const T& lhs, const T& rhs) const
172 {
173 return lhs % rhs;
174 }
175
176 using first_argument_type = T;
177 using second_argument_type = T;
178 using result_type = T;
179 };
180
181 template<class T = void>
182 struct negate
183 {
184 constexpr T operator()(const T& x) const
185 {
186 return -x;
187 }
188
189 using argument_type = T;
190 using result_type = T;
191 };
192
193 namespace aux
194 {
195 /**
196 * Used by some functions like std::set::find to determine
197 * whether a functor is transparent.
198 */
199 struct transparent_t;
200 }
201
202 template<>
203 struct plus<void>
204 {
205 template<class T, class U>
206 constexpr auto operator(T&& lhs, U&& rhs) const
207 -> decltype(forward<T>(lhs) + forward<U>(rhs))
208 {
209 return forward<T>(lhs) + forward<T>(rhs);
210 }
211
212 using is_transparent = aux::transparent_t;
213 };
214
215 template<>
216 struct minus<void>
217 {
218 template<class T, class U>
219 constexpr auto operator(T&& lhs, U&& rhs) const
220 -> decltype(forward<T>(lhs) - forward<U>(rhs))
221 {
222 return forward<T>(lhs) - forward<T>(rhs);
223 }
224
225 using is_transparent = aux::transparent_t;
226 };
227
228 template<>
229 struct multiplies<void>
230 {
231 template<class T, class U>
232 constexpr auto operator(T&& lhs, U&& rhs) const
233 -> decltype(forward<T>(lhs) * forward<U>(rhs))
234 {
235 return forward<T>(lhs) * forward<T>(rhs);
236 }
237
238 using is_transparent = aux::transparent_t;
239 };
240
241 template<>
242 struct divides<void>
243 {
244 template<class T, class U>
245 constexpr auto operator(T&& lhs, U&& rhs) const
246 -> decltype(forward<T>(lhs) / forward<U>(rhs))
247 {
248 return forward<T>(lhs) / forward<T>(rhs);
249 }
250
251 using is_transparent = aux::transparent_t;
252 };
253
254 template<>
255 struct modulus<void>
256 {
257 template<class T, class U>
258 constexpr auto operator(T&& lhs, U&& rhs) const
259 -> decltype(forward<T>(lhs) % forward<U>(rhs))
260 {
261 return forward<T>(lhs) % forward<T>(rhs);
262 }
263
264 using is_transparent = aux::transparent_t;
265 };
266
267 template<>
268 struct negate<void>
269 {
270 template<class T>
271 constexpr auto operator(T&& x) const
272 -> decltype(-forward<T>(x))
273 {
274 return -forward<T>(x);
275 }
276
277 using is_transparent = aux::transparent_t;
278 };
279
280 /**
281 * 20.9.6, comparisons:
282 */
283
284 template<class T = void>
285 struct equal_to;
286 {
287 constexpr bool operator()(const T& lhs, const T& rhs) const
288 {
289 return lhs == rhs;
290 }
291
292 using first_argument_type = T;
293 using second_argument_type = T;
294 using result_type = bool;
295 };
296
297 template<class T = void>
298 struct not_equal_to
299 {
300 constexpr bool operator()(const T& lhs, const T& rhs) const
301 {
302 return lhs != rhs;
303 }
304
305 using first_argument_type = T;
306 using second_argument_type = T;
307 using result_type = bool;
308 };
309
310 template<class T = void>
311 struct greater
312 {
313 constexpr bool operator()(const T& lhs, const T& rhs) const
314 {
315 return lhs > rhs;
316 }
317
318 using first_argument_type = T;
319 using second_argument_type = T;
320 using result_type = bool;
321 };
322
323 template<class T = void>
324 struct less
325 {
326 constexpr bool operator()(const T& lhs, const T& rhs) const
327 {
328 return lhs < rhs;
329 }
330
331 using first_argument_type = T;
332 using second_argument_type = T;
333 using result_type = bool;
334 };
335
336 template<class T = void>
337 struct greater_equal
338 {
339 constexpr bool operator()(const T& lhs, const T& rhs) const
340 {
341 return lhs >= rhs;
342 }
343
344 using first_argument_type = T;
345 using second_argument_type = T;
346 using result_type = bool;
347 };
348
349 template<class T = void>
350 struct less_equal
351 {
352 constexpr bool operator()(const T& lhs, const T& rhs) const
353 {
354 return lhs <= rhs;
355 }
356
357 using first_argument_type = T;
358 using second_argument_type = T;
359 using result_type = bool;
360 };
361
362 template<>
363 struct equal_to<void>
364 {
365 template<class T, class U>
366 constexpr auto operator(T&& lhs, U&& rhs) const
367 -> decltype(forward<T>(lhs) == forward<U>(rhs))
368 {
369 return forward<T>(lhs) == forward<U>(rhs);
370 }
371
372 using is_transparent = aux::transparent_t;
373 };
374
375 template<>
376 struct not_equal_to<void>
377 {
378 template<class T, class U>
379 constexpr auto operator(T&& lhs, U&& rhs) const
380 -> decltype(forward<T>(lhs) != forward<U>(rhs))
381 {
382 return forward<T>(lhs) != forward<U>(rhs);
383 }
384
385 using is_transparent = aux::transparent_t;
386 };
387
388 template<>
389 struct greater<void>
390 {
391 template<class T, class U>
392 constexpr auto operator(T&& lhs, U&& rhs) const
393 -> decltype(forward<T>(lhs) > forward<U>(rhs))
394 {
395 return forward<T>(lhs) > forward<U>(rhs);
396 }
397
398 using is_transparent = aux::transparent_t;
399 };
400
401 template<>
402 struct less<void>
403 {
404 template<class T, class U>
405 constexpr auto operator(T&& lhs, U&& rhs) const
406 -> decltype(forward<T>(lhs) < forward<U>(rhs))
407 {
408 return forward<T>(lhs) < forward<U>(rhs);
409 }
410
411 using is_transparent = aux::transparent_t;
412 };
413
414 template<>
415 struct greater_equal<void>
416 {
417 template<class T, class U>
418 constexpr auto operator(T&& lhs, U&& rhs) const
419 -> decltype(forward<T>(lhs) >= forward<U>(rhs))
420 {
421 return forward<T>(lhs) >= forward<U>(rhs);
422 }
423
424 using is_transparent = aux::transparent_t;
425 };
426
427 template<>
428 struct less_equal<void>
429 {
430 template<class T, class U>
431 constexpr auto operator(T&& lhs, U&& rhs) const
432 -> decltype(forward<T>(lhs) <= forward<U>(rhs))
433 {
434 return forward<T>(lhs) <= forward<U>(rhs);
435 }
436
437 using is_transparent = aux::transparent_t;
438 };
439
440 /**
441 * 20.9.7, logical operations:
442 */
443
444 template<class T = void>
445 struct logical_and
446 {
447 constexpr bool operator()(const T& lhs, const T& rhs) const
448 {
449 return lhs && rhs;
450 }
451
452 using first_argument_type = T;
453 using second_argument_type = T;
454 using result_type = bool;
455 };
456
457 template<class T = void>
458 struct logical_or
459 {
460 constexpr bool operator()(const T& lhs, const T& rhs) const
461 {
462 return lhs || rhs;
463 }
464
465 using first_argument_type = T;
466 using second_argument_type = T;
467 using result_type = bool;
468 };
469
470 template<class T = void>
471 struct logical_not
472 {
473 constexpr bool operator()(const T& x) const
474 {
475 return !x;
476 }
477
478 using argument_type = T;
479 using result_type = bool;
480 };
481
482 template<>
483 struct logical_and<void>
484 {
485 template<class T, class U>
486 constexpr auto operator(T&& lhs, U&& rhs) const
487 -> decltype(forward<T>(lhs) && forward<U>(rhs))
488 {
489 return forward<T>(lhs) && forward<U>(rhs);
490 }
491
492 using is_transparent = aux::transparent_t;
493 };
494
495 template<>
496 struct logical_or<void>
497 {
498 template<class T, class U>
499 constexpr auto operator(T&& lhs, U&& rhs) const
500 -> decltype(forward<T>(lhs) || forward<U>(rhs))
501 {
502 return forward<T>(lhs) || forward<U>(rhs);
503 }
504
505 using is_transparent = aux::transparent_t;
506 };
507
508 template<>
509 struct logical_not<void>
510 {
511 template<class T>
512 constexpr auto operator(T&& x) const
513 -> decltype(!forward<T>(x))
514 {
515 return !forward<T>(lhs);
516 }
517
518 using is_transparent = aux::transparent_t;
519 };
520
521 /**
522 * 20.9.8, bitwise operations:
523 */
524
525 template<class T = void>
526 struct bit_and
527 {
528 constexpr T operator()(const T& lhs, const T& rhs) const
529 {
530 return lhs & rhs;
531 }
532
533 using first_argument_type = T;
534 using second_argument_type = T;
535 using result_type = T;
536 };
537
538 template<class T = void>
539 struct bit_or
540 {
541 constexpr T operator()(const T& lhs, const T& rhs) const
542 {
543 return lhs | rhs;
544 }
545
546 using first_argument_type = T;
547 using second_argument_type = T;
548 using result_type = T;
549 };
550
551 template<class T = void>
552 struct bit_xor
553 {
554 constexpr T operator()(const T& lhs, const T& rhs) const
555 {
556 return lhs ^ rhs;
557 }
558
559 using first_argument_type = T;
560 using second_argument_type = T;
561 using result_type = T;
562 };
563
564 template<class T = void>
565 struct bit_not
566 {
567 constexpr bool operator()(const T& x) const
568 {
569 return ~x;
570 }
571
572 using argument_type = T;
573 using result_type = T;
574 };
575
576 template<>
577 struct bit_and<void>
578 {
579 template<class T, class U>
580 constexpr auto operator(T&& lhs, U&& rhs) const
581 -> decltype(forward<T>(lhs) & forward<U>(rhs))
582 {
583 return forward<T>(lhs) & forward<U>(rhs);
584 }
585
586 using is_transparent = aux::transparent_t;
587 };
588
589 template<>
590 struct bit_or<void>
591 {
592 template<class T, class U>
593 constexpr auto operator(T&& lhs, U&& rhs) const
594 -> decltype(forward<T>(lhs) | forward<U>(rhs))
595 {
596 return forward<T>(lhs) | forward<U>(rhs);
597 }
598
599 using is_transparent = aux::transparent_t;
600 };
601
602 template<>
603 struct bit_xor<void>
604 {
605 template<class T, class U>
606 constexpr auto operator(T&& lhs, U&& rhs) const
607 -> decltype(forward<T>(lhs) ^ forward<U>(rhs))
608 {
609 return forward<T>(lhs) ^ forward<U>(rhs);
610 }
611
612 using is_transparent = aux::transparent_t;
613 };
614
615 template<>
616 struct bit_not<void>
617 {
618 template<class T>
619 constexpr auto operator(T&& x) const
620 -> decltype(~forward<T>(x))
621 {
622 return ~forward<T>(lhs);
623 }
624
625 using is_transparent = aux::transparent_t;
626 };
627
628 /**
629 * 20.9.9, negators:
630 */
631
632 template<class Predicate>
633 class unary_negate;
634
635 template<class Predicate>
636 constexpr unary_negate<Predicate> not1(const Predicate& pred);
637
638 template<class Predicate>
639 class binary_negate;
640
641 template<class Predicate>
642 constexpr binary_negate<Predicate> not2(const Predicate& pred);
643
644 /**
645 * 20.9.10, bind:
646 */
647
648 template<class T>
649 struct is_bind_expression;
650
651 template<class T>
652 struct is_placeholder;
653
654 // TODO: void should be /unspecified/
655 template<class F, class... Args>
656 void bind(F&& f, Args&&... args);
657
658 template<class R, class F, class... Args>
659 void bind(F&& f, Args&&... args);
660
661 namespace placeholders
662 {
663 /**
664 * TODO: for X from 1 to implementation defined M
665 * extern /unspecified/ _X;
666 */
667 }
668
669 /**
670 * 20.9.11, member function adaptors:
671 */
672
673 // TODO: void should be /unspecified/
674 template<class R, class T>
675 void mem_fn(R T::* f);
676
677 /**
678 * 20.9.12, polymorphic function adaptors:
679 */
680
681 class bad_function_call;
682
683 template<class>
684 class function; // undefined
685
686 template<class R, class... Args>
687 class function<R(Args...)>;
688
689 template<class R, class... Args>
690 void swap(function<R(Args...)>& f1, function<R(Args...)>& f2);
691
692 template<class R, class... Args>
693 bool operator==(const function<R(Args...)>&, nullptr_t) noexcept;
694
695 template<class R, class... Args>
696 bool operator==(nullptr_t, const function<R(Args...)>&) noexcept;
697
698 template<class R, class... Args>
699 bool operator!=(const function<R(Args...)>&, nullptr_t) noexcept;
700
701 template<class R, class... Args>
702 bool operator!=(nullptr_t, const function<R(Args...)>&) noexcept;
703
704 /**
705 * 20.9.13, hash function primary template:
706 */
707
708 template<class T>
709 struct hash;
710
711 template<>
712 struct hash<bool>;
713
714 template<>
715 struct hash<char>;
716
717 template<>
718 struct hash<signed char>;
719
720 template<>
721 struct hash<unsigned char>;
722
723 template<>
724 struct hash<char16_t>;
725
726 template<>
727 struct hash<char32_t>;
728
729 template<>
730 struct hash<wchar_t>;
731
732 template<>
733 struct hash<short>;
734
735 template<>
736 struct hash<unsigned short>;
737
738 template<>
739 struct hash<int>;
740
741 template<>
742 struct hash<unsigned int>;
743
744 template<>
745 struct hash<long>;
746
747 template<>
748 struct hash<long long>;
749
750 template<>
751 struct hash<unsigned long>;
752
753 template<>
754 struct hash<unsigned long long>;
755
756 template<>
757 struct hash<float>;
758
759 template<>
760 struct hash<double>;
761
762 template<>
763 struct hash<long double>;
764
765 template<class T>
766 struct hash<T*>;
767}
768
769#endif
Note: See TracBrowser for help on using the repository browser.