source: mainline/uspace/lib/cpp/include/impl/functional.hpp@ 9f77d98

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

cpp: implemented std::hash for primitive types

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