source: mainline/uspace/lib/cpp/include/impl/functional.hpp@ 9396c52

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

fixed compile errors, added a generic hash function, fixed static asserts

  • Property mode set to 100644
File size: 23.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 <limits>
33#include <type_traits>
34#include <utility>
35
36namespace std
37{
38 namespace aux
39 {
40 /**
41 * 20.9.2, requirements:
42 */
43 template<class R, class T, class T1, class... Ts>
44 decltype(auto) invoke(R T::* f, T1&& t1, Ts&&... args)
45 {
46 if constexpr (is_member_function_pointer_v<decltype(f)>)
47 {
48 if constexpr (is_base_of_v<T, remove_reference_t<T1>>)
49 // (1.1)
50 return (t1.*f)(forward<Ts>(args)...);
51 else
52 // (1.2)
53 return ((*t1).*f)(forward<Ts>(args)...);
54 }
55 else if constexpr (is_member_object_pointer_v<decltype(f)> && sizeof...(args) == 0)
56 {
57 /**
58 * Note: Standard requires to N be equal to 1, but we take t1 directly
59 * so we need sizeof...(args) to be 0.
60 */
61 if constexpr (is_base_of_v<T, remove_reference_t<T1>>)
62 // (1.3)
63 return t1.*f;
64 else
65 // (1.4)
66 return (*t1).*f;
67 }
68
69 /**
70 * Note: If this condition holds this will not be reachable,
71 * but a new addition to the standard (17.7 point (8.1))
72 * prohibits us from simply using false as the condition here,
73 * so we use this because we know it is false here.
74 */
75 static_assert(is_member_function_pointer_v<decltype(f)>, "invalid invoke");
76 }
77
78 template<class F, class... Args>
79 decltype(auto) invoke(F&& f, Args&&... args)
80 {
81 // (1.5)
82 return f(forward<Args>(args)...);
83 }
84 }
85
86 /**
87 * 20.9.3, invoke:
88 */
89
90 template<class F, class... Args>
91 result_of_t<F&&(Args&&...)> invoke(F&& f, Args&&... args)
92 {
93 return aux::invoke(forward<F>(f)(forward<Args>(args)...));
94 }
95
96 /**
97 * 20.9.4, reference_wrapper:
98 */
99
100 template<class T>
101 class reference_wrapper;
102
103 template<class T>
104 reference_wrapper<T> ref(T& t) noexcept;
105
106 template<class T>
107 reference_wrapper<const T> cref(const T& t) noexcept;
108
109 template<class T>
110 void ref(const T&&) = delete;
111
112 template<class T>
113 void cref(const T&&) = delete;
114
115 template<class T>
116 reference_wrapper<T> ref(reference_wrapper<T> ref) noexcept;
117
118 template<class T>
119 reference_wrapper<const T> cref(reference_wrapper<T> ref) noexcept;
120
121 /**
122 * 20.9.5, arithmetic operations:
123 */
124
125 template<class T = void>
126 struct plus
127 {
128 constexpr T operator()(const T& lhs, const T& rhs) const
129 {
130 return lhs + rhs;
131 }
132
133 using first_argument_type = T;
134 using second_argument_type = T;
135 using result_type = T;
136 };
137
138 template<class T = void>
139 struct minus
140 {
141 constexpr T operator()(const T& lhs, const T& rhs) const
142 {
143 return lhs - rhs;
144 }
145
146 using first_argument_type = T;
147 using second_argument_type = T;
148 using result_type = T;
149 };
150
151 template<class T = void>
152 struct multiplies
153 {
154 constexpr T operator()(const T& lhs, const T& rhs) const
155 {
156 return lhs * rhs;
157 }
158
159 using first_argument_type = T;
160 using second_argument_type = T;
161 using result_type = T;
162 };
163
164 template<class T = void>
165 struct divides
166 {
167 constexpr T operator()(const T& lhs, const T& rhs) const
168 {
169 return lhs / rhs;
170 }
171
172 using first_argument_type = T;
173 using second_argument_type = T;
174 using result_type = T;
175 };
176
177 template<class T = void>
178 struct modulus
179 {
180 constexpr T operator()(const T& lhs, const T& rhs) const
181 {
182 return lhs % rhs;
183 }
184
185 using first_argument_type = T;
186 using second_argument_type = T;
187 using result_type = T;
188 };
189
190 template<class T = void>
191 struct negate
192 {
193 constexpr T operator()(const T& x) const
194 {
195 return -x;
196 }
197
198 using argument_type = T;
199 using result_type = T;
200 };
201
202 namespace aux
203 {
204 /**
205 * Used by some functions like std::set::find to determine
206 * whether a functor is transparent.
207 */
208 struct transparent_t;
209 }
210
211 template<>
212 struct plus<void>
213 {
214 template<class T, class U>
215 constexpr auto operator()(T&& lhs, U&& rhs) const
216 -> decltype(forward<T>(lhs) + forward<U>(rhs))
217 {
218 return forward<T>(lhs) + forward<T>(rhs);
219 }
220
221 using is_transparent = aux::transparent_t;
222 };
223
224 template<>
225 struct minus<void>
226 {
227 template<class T, class U>
228 constexpr auto operator()(T&& lhs, U&& rhs) const
229 -> decltype(forward<T>(lhs) - forward<U>(rhs))
230 {
231 return forward<T>(lhs) - forward<T>(rhs);
232 }
233
234 using is_transparent = aux::transparent_t;
235 };
236
237 template<>
238 struct multiplies<void>
239 {
240 template<class T, class U>
241 constexpr auto operator()(T&& lhs, U&& rhs) const
242 -> decltype(forward<T>(lhs) * forward<U>(rhs))
243 {
244 return forward<T>(lhs) * forward<T>(rhs);
245 }
246
247 using is_transparent = aux::transparent_t;
248 };
249
250 template<>
251 struct divides<void>
252 {
253 template<class T, class U>
254 constexpr auto operator()(T&& lhs, U&& rhs) const
255 -> decltype(forward<T>(lhs) / forward<U>(rhs))
256 {
257 return forward<T>(lhs) / forward<T>(rhs);
258 }
259
260 using is_transparent = aux::transparent_t;
261 };
262
263 template<>
264 struct modulus<void>
265 {
266 template<class T, class U>
267 constexpr auto operator()(T&& lhs, U&& rhs) const
268 -> decltype(forward<T>(lhs) % forward<U>(rhs))
269 {
270 return forward<T>(lhs) % forward<T>(rhs);
271 }
272
273 using is_transparent = aux::transparent_t;
274 };
275
276 template<>
277 struct negate<void>
278 {
279 template<class T>
280 constexpr auto operator()(T&& x) const
281 -> decltype(-forward<T>(x))
282 {
283 return -forward<T>(x);
284 }
285
286 using is_transparent = aux::transparent_t;
287 };
288
289 /**
290 * 20.9.6, comparisons:
291 */
292
293 template<class T = void>
294 struct equal_to
295 {
296 constexpr bool operator()(const T& lhs, const T& rhs) const
297 {
298 return lhs == rhs;
299 }
300
301 using first_argument_type = T;
302 using second_argument_type = T;
303 using result_type = bool;
304 };
305
306 template<class T = void>
307 struct not_equal_to
308 {
309 constexpr bool operator()(const T& lhs, const T& rhs) const
310 {
311 return lhs != rhs;
312 }
313
314 using first_argument_type = T;
315 using second_argument_type = T;
316 using result_type = bool;
317 };
318
319 template<class T = void>
320 struct greater
321 {
322 constexpr bool operator()(const T& lhs, const T& rhs) const
323 {
324 return lhs > rhs;
325 }
326
327 using first_argument_type = T;
328 using second_argument_type = T;
329 using result_type = bool;
330 };
331
332 template<class T = void>
333 struct less
334 {
335 constexpr bool operator()(const T& lhs, const T& rhs) const
336 {
337 return lhs < rhs;
338 }
339
340 using first_argument_type = T;
341 using second_argument_type = T;
342 using result_type = bool;
343 };
344
345 template<class T = void>
346 struct greater_equal
347 {
348 constexpr bool operator()(const T& lhs, const T& rhs) const
349 {
350 return lhs >= rhs;
351 }
352
353 using first_argument_type = T;
354 using second_argument_type = T;
355 using result_type = bool;
356 };
357
358 template<class T = void>
359 struct less_equal
360 {
361 constexpr bool operator()(const T& lhs, const T& rhs) const
362 {
363 return lhs <= rhs;
364 }
365
366 using first_argument_type = T;
367 using second_argument_type = T;
368 using result_type = bool;
369 };
370
371 template<>
372 struct equal_to<void>
373 {
374 template<class T, class U>
375 constexpr auto operator()(T&& lhs, U&& rhs) const
376 -> decltype(forward<T>(lhs) == forward<U>(rhs))
377 {
378 return forward<T>(lhs) == forward<U>(rhs);
379 }
380
381 using is_transparent = aux::transparent_t;
382 };
383
384 template<>
385 struct not_equal_to<void>
386 {
387 template<class T, class U>
388 constexpr auto operator()(T&& lhs, U&& rhs) const
389 -> decltype(forward<T>(lhs) != forward<U>(rhs))
390 {
391 return forward<T>(lhs) != forward<U>(rhs);
392 }
393
394 using is_transparent = aux::transparent_t;
395 };
396
397 template<>
398 struct greater<void>
399 {
400 template<class T, class U>
401 constexpr auto operator()(T&& lhs, U&& rhs) const
402 -> decltype(forward<T>(lhs) > forward<U>(rhs))
403 {
404 return forward<T>(lhs) > forward<U>(rhs);
405 }
406
407 using is_transparent = aux::transparent_t;
408 };
409
410 template<>
411 struct less<void>
412 {
413 template<class T, class U>
414 constexpr auto operator()(T&& lhs, U&& rhs) const
415 -> decltype(forward<T>(lhs) < forward<U>(rhs))
416 {
417 return forward<T>(lhs) < forward<U>(rhs);
418 }
419
420 using is_transparent = aux::transparent_t;
421 };
422
423 template<>
424 struct greater_equal<void>
425 {
426 template<class T, class U>
427 constexpr auto operator()(T&& lhs, U&& rhs) const
428 -> decltype(forward<T>(lhs) >= forward<U>(rhs))
429 {
430 return forward<T>(lhs) >= forward<U>(rhs);
431 }
432
433 using is_transparent = aux::transparent_t;
434 };
435
436 template<>
437 struct less_equal<void>
438 {
439 template<class T, class U>
440 constexpr auto operator()(T&& lhs, U&& rhs) const
441 -> decltype(forward<T>(lhs) <= forward<U>(rhs))
442 {
443 return forward<T>(lhs) <= forward<U>(rhs);
444 }
445
446 using is_transparent = aux::transparent_t;
447 };
448
449 /**
450 * 20.9.7, logical operations:
451 */
452
453 template<class T = void>
454 struct logical_and
455 {
456 constexpr bool operator()(const T& lhs, const T& rhs) const
457 {
458 return lhs && rhs;
459 }
460
461 using first_argument_type = T;
462 using second_argument_type = T;
463 using result_type = bool;
464 };
465
466 template<class T = void>
467 struct logical_or
468 {
469 constexpr bool operator()(const T& lhs, const T& rhs) const
470 {
471 return lhs || rhs;
472 }
473
474 using first_argument_type = T;
475 using second_argument_type = T;
476 using result_type = bool;
477 };
478
479 template<class T = void>
480 struct logical_not
481 {
482 constexpr bool operator()(const T& x) const
483 {
484 return !x;
485 }
486
487 using argument_type = T;
488 using result_type = bool;
489 };
490
491 template<>
492 struct logical_and<void>
493 {
494 template<class T, class U>
495 constexpr auto operator()(T&& lhs, U&& rhs) const
496 -> decltype(forward<T>(lhs) && forward<U>(rhs))
497 {
498 return forward<T>(lhs) && forward<U>(rhs);
499 }
500
501 using is_transparent = aux::transparent_t;
502 };
503
504 template<>
505 struct logical_or<void>
506 {
507 template<class T, class U>
508 constexpr auto operator()(T&& lhs, U&& rhs) const
509 -> decltype(forward<T>(lhs) || forward<U>(rhs))
510 {
511 return forward<T>(lhs) || forward<U>(rhs);
512 }
513
514 using is_transparent = aux::transparent_t;
515 };
516
517 template<>
518 struct logical_not<void>
519 {
520 template<class T>
521 constexpr auto operator()(T&& x) const
522 -> decltype(!forward<T>(x))
523 {
524 return !forward<T>(x);
525 }
526
527 using is_transparent = aux::transparent_t;
528 };
529
530 /**
531 * 20.9.8, bitwise operations:
532 */
533
534 template<class T = void>
535 struct bit_and
536 {
537 constexpr T operator()(const T& lhs, const T& rhs) const
538 {
539 return lhs & rhs;
540 }
541
542 using first_argument_type = T;
543 using second_argument_type = T;
544 using result_type = T;
545 };
546
547 template<class T = void>
548 struct bit_or
549 {
550 constexpr T operator()(const T& lhs, const T& rhs) const
551 {
552 return lhs | rhs;
553 }
554
555 using first_argument_type = T;
556 using second_argument_type = T;
557 using result_type = T;
558 };
559
560 template<class T = void>
561 struct bit_xor
562 {
563 constexpr T operator()(const T& lhs, const T& rhs) const
564 {
565 return lhs ^ rhs;
566 }
567
568 using first_argument_type = T;
569 using second_argument_type = T;
570 using result_type = T;
571 };
572
573 template<class T = void>
574 struct bit_not
575 {
576 constexpr bool operator()(const T& x) const
577 {
578 return ~x;
579 }
580
581 using argument_type = T;
582 using result_type = T;
583 };
584
585 template<>
586 struct bit_and<void>
587 {
588 template<class T, class U>
589 constexpr auto operator()(T&& lhs, U&& rhs) const
590 -> decltype(forward<T>(lhs) & forward<U>(rhs))
591 {
592 return forward<T>(lhs) & forward<U>(rhs);
593 }
594
595 using is_transparent = aux::transparent_t;
596 };
597
598 template<>
599 struct bit_or<void>
600 {
601 template<class T, class U>
602 constexpr auto operator()(T&& lhs, U&& rhs) const
603 -> decltype(forward<T>(lhs) | forward<U>(rhs))
604 {
605 return forward<T>(lhs) | forward<U>(rhs);
606 }
607
608 using is_transparent = aux::transparent_t;
609 };
610
611 template<>
612 struct bit_xor<void>
613 {
614 template<class T, class U>
615 constexpr auto operator()(T&& lhs, U&& rhs) const
616 -> decltype(forward<T>(lhs) ^ forward<U>(rhs))
617 {
618 return forward<T>(lhs) ^ forward<U>(rhs);
619 }
620
621 using is_transparent = aux::transparent_t;
622 };
623
624 template<>
625 struct bit_not<void>
626 {
627 template<class T>
628 constexpr auto operator()(T&& x) const
629 -> decltype(~forward<T>(x))
630 {
631 return ~forward<T>(x);
632 }
633
634 using is_transparent = aux::transparent_t;
635 };
636
637 /**
638 * 20.9.9, negators:
639 */
640
641 template<class Predicate>
642 class unary_negate;
643
644 template<class Predicate>
645 constexpr unary_negate<Predicate> not1(const Predicate& pred);
646
647 template<class Predicate>
648 class binary_negate;
649
650 template<class Predicate>
651 constexpr binary_negate<Predicate> not2(const Predicate& pred);
652
653 /**
654 * 20.9.10, bind:
655 */
656
657 template<class T>
658 struct is_bind_expression;
659
660 template<class T>
661 struct is_placeholder;
662
663 // TODO: void should be /unspecified/
664 template<class F, class... Args>
665 void bind(F&& f, Args&&... args);
666
667 template<class R, class F, class... Args>
668 void bind(F&& f, Args&&... args);
669
670 namespace placeholders
671 {
672 /**
673 * TODO: for X from 1 to implementation defined M
674 * extern /unspecified/ _X;
675 */
676 }
677
678 /**
679 * 20.9.11, member function adaptors:
680 */
681
682 // TODO: void should be /unspecified/
683 template<class R, class T>
684 void mem_fn(R T::* f);
685
686 /**
687 * 20.9.12, polymorphic function adaptors:
688 */
689
690 class bad_function_call;
691
692 template<class>
693 class function; // undefined
694
695 template<class R, class... Args>
696 class function<R(Args...)>;
697
698 template<class R, class... Args>
699 void swap(function<R(Args...)>& f1, function<R(Args...)>& f2);
700
701 template<class R, class... Args>
702 bool operator==(const function<R(Args...)>&, nullptr_t) noexcept;
703
704 template<class R, class... Args>
705 bool operator==(nullptr_t, const function<R(Args...)>&) noexcept;
706
707 template<class R, class... Args>
708 bool operator!=(const function<R(Args...)>&, nullptr_t) noexcept;
709
710 template<class R, class... Args>
711 bool operator!=(nullptr_t, const function<R(Args...)>&) noexcept;
712
713 /**
714 * 20.9.13, hash function primary template:
715 */
716
717 namespace aux
718 {
719 template<class T>
720 union converter
721 {
722 T value;
723 uint64_t converted;
724 };
725
726 template<class T>
727 T hash_(uint64_t x) noexcept
728 {
729 // TODO: This is copied form adt/hash (temporarily),
730 // check if we can use something better.
731 x = (x ^ 61) ^ (x >> 16);
732 x = x + (x << 3);
733 x = x ^ (x >> 4);
734 x = x * 0x27d4eb2d;
735 x = x ^ (x >> 15);
736
737 return static_cast<T>((x << 32) | (x >> 32));
738 }
739
740 template<class T>
741 size_t hash(T x) noexcept
742 {
743 static_assert(is_arithmetic_v<T> || is_pointer_v<T>,
744 "invalid type passed to aux::hash");
745
746 converter<T> conv;
747 conv.value = x;
748
749 return hash_<size_t>(conv.converted);
750 }
751 }
752
753 template<class T>
754 struct hash
755 { /* DUMMY BODY */ };
756
757 template<>
758 struct hash<bool>
759 {
760 size_t operator()(bool x) const noexcept
761 {
762 return aux::hash(x);
763 }
764
765 using argument_type = bool;
766 using result_type = size_t;
767 };
768
769 template<>
770 struct hash<char>
771 {
772 size_t operator()(char x) const noexcept
773 {
774 return aux::hash(x);
775 }
776
777 using argument_type = char;
778 using result_type = size_t;
779 };
780
781 template<>
782 struct hash<signed char>
783 {
784 size_t operator()(signed char x) const noexcept
785 {
786 return aux::hash(x);
787 }
788
789 using argument_type = signed char;
790 using result_type = size_t;
791 };
792
793 template<>
794 struct hash<unsigned char>
795 {
796 size_t operator()(unsigned char x) const noexcept
797 {
798 return aux::hash(x);
799 }
800
801 using argument_type = unsigned char;
802 using result_type = size_t;
803 };
804
805 template<>
806 struct hash<char16_t>
807 {
808 size_t operator()(char16_t x) const noexcept
809 {
810 return aux::hash(x);
811 }
812
813 using argument_type = char16_t;
814 using result_type = size_t;
815 };
816
817 template<>
818 struct hash<char32_t>
819 {
820 size_t operator()(char32_t x) const noexcept
821 {
822 return aux::hash(x);
823 }
824
825 using argument_type = char32_t;
826 using result_type = size_t;
827 };
828
829 template<>
830 struct hash<wchar_t>
831 {
832 size_t operator()(wchar_t x) const noexcept
833 {
834 return aux::hash(x);
835 }
836
837 using argument_type = wchar_t;
838 using result_type = size_t;
839 };
840
841 template<>
842 struct hash<short>
843 {
844 size_t operator()(short x) const noexcept
845 {
846 return aux::hash(x);
847 }
848
849 using argument_type = short;
850 using result_type = size_t;
851 };
852
853 template<>
854 struct hash<unsigned short>
855 {
856 size_t operator()(unsigned short x) const noexcept
857 {
858 return aux::hash(x);
859 }
860
861 using argument_type = unsigned short;
862 using result_type = size_t;
863 };
864
865 template<>
866 struct hash<int>
867 {
868 size_t operator()(int x) const noexcept
869 {
870 return aux::hash(x);
871 }
872
873 using argument_type = int;
874 using result_type = size_t;
875 };
876
877 template<>
878 struct hash<unsigned int>
879 {
880 size_t operator()(unsigned int x) const noexcept
881 {
882 return aux::hash(x);
883 }
884
885 using argument_type = unsigned int;
886 using result_type = size_t;
887 };
888
889 template<>
890 struct hash<long>
891 {
892 size_t operator()(long x) const noexcept
893 {
894 return aux::hash(x);
895 }
896
897 using argument_type = long;
898 using result_type = size_t;
899 };
900
901 template<>
902 struct hash<long long>
903 {
904 size_t operator()(long long x) const noexcept
905 {
906 return aux::hash(x);
907 }
908
909 using argument_type = long long;
910 using result_type = size_t;
911 };
912
913 template<>
914 struct hash<unsigned long>
915 {
916 size_t operator()(unsigned long x) const noexcept
917 {
918 return aux::hash(x);
919 }
920
921 using argument_type = unsigned long;
922 using result_type = size_t;
923 };
924
925 template<>
926 struct hash<unsigned long long>
927 {
928 size_t operator()(unsigned long long x) const noexcept
929 {
930 return aux::hash(x);
931 }
932
933 using argument_type = unsigned long long;
934 using result_type = size_t;
935 };
936
937 template<>
938 struct hash<float>
939 {
940 size_t operator()(float x) const noexcept
941 {
942 return aux::hash(x);
943 }
944
945 using argument_type = float;
946 using result_type = size_t;
947 };
948
949 template<>
950 struct hash<double>
951 {
952 size_t operator()(double x) const noexcept
953 {
954 return aux::hash(x);
955 }
956
957 using argument_type = double;
958 using result_type = size_t;
959 };
960
961 template<>
962 struct hash<long double>
963 {
964 size_t operator()(long double x) const noexcept
965 {
966 return aux::hash(x);
967 }
968
969 using argument_type = long double;
970 using result_type = size_t;
971 };
972
973 template<class T>
974 struct hash<T*>
975 {
976 size_t operator()(T* x) const noexcept
977 {
978 return aux::hash(x);
979 }
980
981 using argument_type = T*;
982 using result_type = size_t;
983 };
984}
985
986#endif
Note: See TracBrowser for help on using the repository browser.