source: mainline/uspace/lib/cpp/include/impl/functional.hpp@ 614b07e

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

cpp: split too big files into smaller (loosely related) sub files

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