source: mainline/uspace/lib/cpp/include/impl/functional.hpp@ 08be4a4

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

cpp: added a way to check if a functor is transparent

  • Property mode set to 100644
File size: 24.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 <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 public:
104 using type = T;
105 // TODO: conditional typedefs
106
107 reference_wrapper(type& val) noexcept
108 : data_{&val}
109 { /* DUMMY BODY */ }
110
111 reference_wrapper(type&&) = delete;
112
113 reference_wrapper(const reference_wrapper& other) noexcept
114 : data_{other.data_}
115 { /* DUMMY BODY */ }
116
117 reference_wrapper& operator=(const reference_wrapper& other) noexcept
118 {
119 data_ = other.data_;
120
121 return *this;
122 }
123
124 operator type&() const noexcept
125 {
126 return *data_;
127 }
128
129 type& get() const noexcept
130 {
131 return *data_;
132 }
133
134 template<class... Args>
135 result_of_t<type&(Args&&...)> operator()(Args&&... args) const
136 {
137 return invoke(*data_, std::forward<Args>(args)...);
138 }
139
140 private:
141 type* data_;
142 };
143
144 template<class T>
145 reference_wrapper<T> ref(T& t) noexcept
146 {
147 return reference_wrapper<T>{t};
148 }
149
150 template<class T>
151 reference_wrapper<const T> cref(const T& t) noexcept
152 {
153 return reference_wrapper<const T>{t};
154 }
155
156 template<class T>
157 void ref(const T&&) = delete;
158
159 template<class T>
160 void cref(const T&&) = delete;
161
162 template<class T>
163 reference_wrapper<T> ref(reference_wrapper<T> t) noexcept
164 {
165 return ref(t.get());
166 }
167
168 template<class T>
169 reference_wrapper<const T> cref(reference_wrapper<T> t) noexcept
170 {
171 return cref(t.get());
172 }
173
174 /**
175 * 20.9.5, arithmetic operations:
176 */
177
178 template<class T = void>
179 struct plus
180 {
181 constexpr T operator()(const T& lhs, const T& rhs) const
182 {
183 return lhs + rhs;
184 }
185
186 using first_argument_type = T;
187 using second_argument_type = T;
188 using result_type = T;
189 };
190
191 template<class T = void>
192 struct minus
193 {
194 constexpr T operator()(const T& lhs, const T& rhs) const
195 {
196 return lhs - rhs;
197 }
198
199 using first_argument_type = T;
200 using second_argument_type = T;
201 using result_type = T;
202 };
203
204 template<class T = void>
205 struct multiplies
206 {
207 constexpr T operator()(const T& lhs, const T& rhs) const
208 {
209 return lhs * rhs;
210 }
211
212 using first_argument_type = T;
213 using second_argument_type = T;
214 using result_type = T;
215 };
216
217 template<class T = void>
218 struct divides
219 {
220 constexpr T operator()(const T& lhs, const T& rhs) const
221 {
222 return lhs / rhs;
223 }
224
225 using first_argument_type = T;
226 using second_argument_type = T;
227 using result_type = T;
228 };
229
230 template<class T = void>
231 struct modulus
232 {
233 constexpr T operator()(const T& lhs, const T& rhs) const
234 {
235 return lhs % rhs;
236 }
237
238 using first_argument_type = T;
239 using second_argument_type = T;
240 using result_type = T;
241 };
242
243 template<class T = void>
244 struct negate
245 {
246 constexpr T operator()(const T& x) const
247 {
248 return -x;
249 }
250
251 using argument_type = T;
252 using result_type = T;
253 };
254
255 namespace aux
256 {
257 /**
258 * Used by some functions like std::set::find to determine
259 * whether a functor is transparent.
260 */
261 struct transparent_t;
262
263 template<class T, class = void>
264 struct is_transparent: false_type
265 { /* DUMMY BODY */ };
266
267 template<class T>
268 struct is_transparent<T, void_t<typename T::is_transparent>>
269 : true_type
270 { /* DUMMY BODY */ };
271
272 template<class T>
273 inline constexpr bool is_transparent_v = is_transparent<T>::value;
274 }
275
276 template<>
277 struct plus<void>
278 {
279 template<class T, class U>
280 constexpr auto operator()(T&& lhs, U&& rhs) const
281 -> decltype(forward<T>(lhs) + forward<U>(rhs))
282 {
283 return forward<T>(lhs) + forward<T>(rhs);
284 }
285
286 using is_transparent = aux::transparent_t;
287 };
288
289 template<>
290 struct minus<void>
291 {
292 template<class T, class U>
293 constexpr auto operator()(T&& lhs, U&& rhs) const
294 -> decltype(forward<T>(lhs) - forward<U>(rhs))
295 {
296 return forward<T>(lhs) - forward<T>(rhs);
297 }
298
299 using is_transparent = aux::transparent_t;
300 };
301
302 template<>
303 struct multiplies<void>
304 {
305 template<class T, class U>
306 constexpr auto operator()(T&& lhs, U&& rhs) const
307 -> decltype(forward<T>(lhs) * forward<U>(rhs))
308 {
309 return forward<T>(lhs) * forward<T>(rhs);
310 }
311
312 using is_transparent = aux::transparent_t;
313 };
314
315 template<>
316 struct divides<void>
317 {
318 template<class T, class U>
319 constexpr auto operator()(T&& lhs, U&& rhs) const
320 -> decltype(forward<T>(lhs) / forward<U>(rhs))
321 {
322 return forward<T>(lhs) / forward<T>(rhs);
323 }
324
325 using is_transparent = aux::transparent_t;
326 };
327
328 template<>
329 struct modulus<void>
330 {
331 template<class T, class U>
332 constexpr auto operator()(T&& lhs, U&& rhs) const
333 -> decltype(forward<T>(lhs) % forward<U>(rhs))
334 {
335 return forward<T>(lhs) % forward<T>(rhs);
336 }
337
338 using is_transparent = aux::transparent_t;
339 };
340
341 template<>
342 struct negate<void>
343 {
344 template<class T>
345 constexpr auto operator()(T&& x) const
346 -> decltype(-forward<T>(x))
347 {
348 return -forward<T>(x);
349 }
350
351 using is_transparent = aux::transparent_t;
352 };
353
354 /**
355 * 20.9.6, comparisons:
356 */
357
358 template<class T = void>
359 struct equal_to
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<class T = void>
372 struct not_equal_to
373 {
374 constexpr bool operator()(const T& lhs, const T& rhs) const
375 {
376 return lhs != rhs;
377 }
378
379 using first_argument_type = T;
380 using second_argument_type = T;
381 using result_type = bool;
382 };
383
384 template<class T = void>
385 struct greater
386 {
387 constexpr bool operator()(const T& lhs, const T& rhs) const
388 {
389 return lhs > rhs;
390 }
391
392 using first_argument_type = T;
393 using second_argument_type = T;
394 using result_type = bool;
395 };
396
397 template<class T = void>
398 struct less
399 {
400 constexpr bool operator()(const T& lhs, const T& rhs) const
401 {
402 return lhs < rhs;
403 }
404
405 using first_argument_type = T;
406 using second_argument_type = T;
407 using result_type = bool;
408 };
409
410 template<class T = void>
411 struct greater_equal
412 {
413 constexpr bool operator()(const T& lhs, const T& rhs) const
414 {
415 return lhs >= rhs;
416 }
417
418 using first_argument_type = T;
419 using second_argument_type = T;
420 using result_type = bool;
421 };
422
423 template<class T = void>
424 struct less_equal
425 {
426 constexpr bool operator()(const T& lhs, const T& rhs) const
427 {
428 return lhs <= rhs;
429 }
430
431 using first_argument_type = T;
432 using second_argument_type = T;
433 using result_type = bool;
434 };
435
436 template<>
437 struct equal_to<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 template<>
450 struct not_equal_to<void>
451 {
452 template<class T, class U>
453 constexpr auto operator()(T&& lhs, U&& rhs) const
454 -> decltype(forward<T>(lhs) != forward<U>(rhs))
455 {
456 return forward<T>(lhs) != forward<U>(rhs);
457 }
458
459 using is_transparent = aux::transparent_t;
460 };
461
462 template<>
463 struct greater<void>
464 {
465 template<class T, class U>
466 constexpr auto operator()(T&& lhs, U&& rhs) const
467 -> decltype(forward<T>(lhs) > forward<U>(rhs))
468 {
469 return forward<T>(lhs) > forward<U>(rhs);
470 }
471
472 using is_transparent = aux::transparent_t;
473 };
474
475 template<>
476 struct less<void>
477 {
478 template<class T, class U>
479 constexpr auto operator()(T&& lhs, U&& rhs) const
480 -> decltype(forward<T>(lhs) < forward<U>(rhs))
481 {
482 return forward<T>(lhs) < forward<U>(rhs);
483 }
484
485 using is_transparent = aux::transparent_t;
486 };
487
488 template<>
489 struct greater_equal<void>
490 {
491 template<class T, class U>
492 constexpr auto operator()(T&& lhs, U&& rhs) const
493 -> decltype(forward<T>(lhs) >= forward<U>(rhs))
494 {
495 return forward<T>(lhs) >= forward<U>(rhs);
496 }
497
498 using is_transparent = aux::transparent_t;
499 };
500
501 template<>
502 struct less_equal<void>
503 {
504 template<class T, class U>
505 constexpr auto operator()(T&& lhs, U&& rhs) const
506 -> decltype(forward<T>(lhs) <= forward<U>(rhs))
507 {
508 return forward<T>(lhs) <= forward<U>(rhs);
509 }
510
511 using is_transparent = aux::transparent_t;
512 };
513
514 /**
515 * 20.9.7, logical operations:
516 */
517
518 template<class T = void>
519 struct logical_and
520 {
521 constexpr bool operator()(const T& lhs, const T& rhs) const
522 {
523 return lhs && rhs;
524 }
525
526 using first_argument_type = T;
527 using second_argument_type = T;
528 using result_type = bool;
529 };
530
531 template<class T = void>
532 struct logical_or
533 {
534 constexpr bool operator()(const T& lhs, const T& rhs) const
535 {
536 return lhs || rhs;
537 }
538
539 using first_argument_type = T;
540 using second_argument_type = T;
541 using result_type = bool;
542 };
543
544 template<class T = void>
545 struct logical_not
546 {
547 constexpr bool operator()(const T& x) const
548 {
549 return !x;
550 }
551
552 using argument_type = T;
553 using result_type = bool;
554 };
555
556 template<>
557 struct logical_and<void>
558 {
559 template<class T, class U>
560 constexpr auto operator()(T&& lhs, U&& rhs) const
561 -> decltype(forward<T>(lhs) && forward<U>(rhs))
562 {
563 return forward<T>(lhs) && forward<U>(rhs);
564 }
565
566 using is_transparent = aux::transparent_t;
567 };
568
569 template<>
570 struct logical_or<void>
571 {
572 template<class T, class U>
573 constexpr auto operator()(T&& lhs, U&& rhs) const
574 -> decltype(forward<T>(lhs) || forward<U>(rhs))
575 {
576 return forward<T>(lhs) || forward<U>(rhs);
577 }
578
579 using is_transparent = aux::transparent_t;
580 };
581
582 template<>
583 struct logical_not<void>
584 {
585 template<class T>
586 constexpr auto operator()(T&& x) const
587 -> decltype(!forward<T>(x))
588 {
589 return !forward<T>(x);
590 }
591
592 using is_transparent = aux::transparent_t;
593 };
594
595 /**
596 * 20.9.8, bitwise operations:
597 */
598
599 template<class T = void>
600 struct bit_and
601 {
602 constexpr T operator()(const T& lhs, const T& rhs) const
603 {
604 return lhs & rhs;
605 }
606
607 using first_argument_type = T;
608 using second_argument_type = T;
609 using result_type = T;
610 };
611
612 template<class T = void>
613 struct bit_or
614 {
615 constexpr T operator()(const T& lhs, const T& rhs) const
616 {
617 return lhs | rhs;
618 }
619
620 using first_argument_type = T;
621 using second_argument_type = T;
622 using result_type = T;
623 };
624
625 template<class T = void>
626 struct bit_xor
627 {
628 constexpr T operator()(const T& lhs, const T& rhs) const
629 {
630 return lhs ^ rhs;
631 }
632
633 using first_argument_type = T;
634 using second_argument_type = T;
635 using result_type = T;
636 };
637
638 template<class T = void>
639 struct bit_not
640 {
641 constexpr bool operator()(const T& x) const
642 {
643 return ~x;
644 }
645
646 using argument_type = T;
647 using result_type = T;
648 };
649
650 template<>
651 struct bit_and<void>
652 {
653 template<class T, class U>
654 constexpr auto operator()(T&& lhs, U&& rhs) const
655 -> decltype(forward<T>(lhs) & forward<U>(rhs))
656 {
657 return forward<T>(lhs) & forward<U>(rhs);
658 }
659
660 using is_transparent = aux::transparent_t;
661 };
662
663 template<>
664 struct bit_or<void>
665 {
666 template<class T, class U>
667 constexpr auto operator()(T&& lhs, U&& rhs) const
668 -> decltype(forward<T>(lhs) | forward<U>(rhs))
669 {
670 return forward<T>(lhs) | forward<U>(rhs);
671 }
672
673 using is_transparent = aux::transparent_t;
674 };
675
676 template<>
677 struct bit_xor<void>
678 {
679 template<class T, class U>
680 constexpr auto operator()(T&& lhs, U&& rhs) const
681 -> decltype(forward<T>(lhs) ^ forward<U>(rhs))
682 {
683 return forward<T>(lhs) ^ forward<U>(rhs);
684 }
685
686 using is_transparent = aux::transparent_t;
687 };
688
689 template<>
690 struct bit_not<void>
691 {
692 template<class T>
693 constexpr auto operator()(T&& x) const
694 -> decltype(~forward<T>(x))
695 {
696 return ~forward<T>(x);
697 }
698
699 using is_transparent = aux::transparent_t;
700 };
701
702 /**
703 * 20.9.9, negators:
704 */
705
706 template<class Predicate>
707 class unary_negate;
708
709 template<class Predicate>
710 constexpr unary_negate<Predicate> not1(const Predicate& pred);
711
712 template<class Predicate>
713 class binary_negate;
714
715 template<class Predicate>
716 constexpr binary_negate<Predicate> not2(const Predicate& pred);
717
718 /**
719 * 20.9.10, bind:
720 */
721
722 template<class T>
723 struct is_bind_expression;
724
725 template<class T>
726 struct is_placeholder;
727
728 // TODO: void should be /unspecified/
729 template<class F, class... Args>
730 void bind(F&& f, Args&&... args);
731
732 template<class R, class F, class... Args>
733 void bind(F&& f, Args&&... args);
734
735 namespace placeholders
736 {
737 /**
738 * TODO: for X from 1 to implementation defined M
739 * extern /unspecified/ _X;
740 */
741 }
742
743 /**
744 * 20.9.11, member function adaptors:
745 */
746
747 // TODO: void should be /unspecified/
748 template<class R, class T>
749 void mem_fn(R T::* f);
750
751 /**
752 * 20.9.12, polymorphic function adaptors:
753 */
754
755 class bad_function_call;
756
757 template<class>
758 class function; // undefined
759
760 template<class R, class... Args>
761 class function<R(Args...)>;
762
763 template<class R, class... Args>
764 void swap(function<R(Args...)>& f1, function<R(Args...)>& f2);
765
766 template<class R, class... Args>
767 bool operator==(const function<R(Args...)>&, nullptr_t) noexcept;
768
769 template<class R, class... Args>
770 bool operator==(nullptr_t, const function<R(Args...)>&) noexcept;
771
772 template<class R, class... Args>
773 bool operator!=(const function<R(Args...)>&, nullptr_t) noexcept;
774
775 template<class R, class... Args>
776 bool operator!=(nullptr_t, const function<R(Args...)>&) noexcept;
777
778 /**
779 * 20.9.13, hash function primary template:
780 */
781
782 namespace aux
783 {
784 template<class T>
785 union converter
786 {
787 T value;
788 uint64_t converted;
789 };
790
791 template<class T>
792 T hash_(uint64_t x) noexcept
793 {
794 /**
795 * Note: std::hash is used for indexing in
796 * unordered containers, not for cryptography.
797 * Because of this, we decided to simply convert
798 * the value to uin64_t, which will help us
799 * with testing (since in order to create
800 * a collision in a multiset or multimap
801 * we simply need 2 values that congruent
802 * by the size of the table.
803 */
804 return static_cast<T>(x);
805 }
806
807 template<class T>
808 size_t hash(T x) noexcept
809 {
810 static_assert(is_arithmetic_v<T> || is_pointer_v<T>,
811 "invalid type passed to aux::hash");
812
813 converter<T> conv;
814 conv.value = x;
815
816 return hash_<size_t>(conv.converted);
817 }
818 }
819
820 template<class T>
821 struct hash
822 { /* DUMMY BODY */ };
823
824 template<>
825 struct hash<bool>
826 {
827 size_t operator()(bool x) const noexcept
828 {
829 return aux::hash(x);
830 }
831
832 using argument_type = bool;
833 using result_type = size_t;
834 };
835
836 template<>
837 struct hash<char>
838 {
839 size_t operator()(char x) const noexcept
840 {
841 return aux::hash(x);
842 }
843
844 using argument_type = char;
845 using result_type = size_t;
846 };
847
848 template<>
849 struct hash<signed char>
850 {
851 size_t operator()(signed char x) const noexcept
852 {
853 return aux::hash(x);
854 }
855
856 using argument_type = signed char;
857 using result_type = size_t;
858 };
859
860 template<>
861 struct hash<unsigned char>
862 {
863 size_t operator()(unsigned char x) const noexcept
864 {
865 return aux::hash(x);
866 }
867
868 using argument_type = unsigned char;
869 using result_type = size_t;
870 };
871
872 template<>
873 struct hash<char16_t>
874 {
875 size_t operator()(char16_t x) const noexcept
876 {
877 return aux::hash(x);
878 }
879
880 using argument_type = char16_t;
881 using result_type = size_t;
882 };
883
884 template<>
885 struct hash<char32_t>
886 {
887 size_t operator()(char32_t x) const noexcept
888 {
889 return aux::hash(x);
890 }
891
892 using argument_type = char32_t;
893 using result_type = size_t;
894 };
895
896 template<>
897 struct hash<wchar_t>
898 {
899 size_t operator()(wchar_t x) const noexcept
900 {
901 return aux::hash(x);
902 }
903
904 using argument_type = wchar_t;
905 using result_type = size_t;
906 };
907
908 template<>
909 struct hash<short>
910 {
911 size_t operator()(short x) const noexcept
912 {
913 return aux::hash(x);
914 }
915
916 using argument_type = short;
917 using result_type = size_t;
918 };
919
920 template<>
921 struct hash<unsigned short>
922 {
923 size_t operator()(unsigned short x) const noexcept
924 {
925 return aux::hash(x);
926 }
927
928 using argument_type = unsigned short;
929 using result_type = size_t;
930 };
931
932 template<>
933 struct hash<int>
934 {
935 size_t operator()(int x) const noexcept
936 {
937 return aux::hash(x);
938 }
939
940 using argument_type = int;
941 using result_type = size_t;
942 };
943
944 template<>
945 struct hash<unsigned int>
946 {
947 size_t operator()(unsigned int x) const noexcept
948 {
949 return aux::hash(x);
950 }
951
952 using argument_type = unsigned int;
953 using result_type = size_t;
954 };
955
956 template<>
957 struct hash<long>
958 {
959 size_t operator()(long x) const noexcept
960 {
961 return aux::hash(x);
962 }
963
964 using argument_type = long;
965 using result_type = size_t;
966 };
967
968 template<>
969 struct hash<long long>
970 {
971 size_t operator()(long long x) const noexcept
972 {
973 return aux::hash(x);
974 }
975
976 using argument_type = long long;
977 using result_type = size_t;
978 };
979
980 template<>
981 struct hash<unsigned long>
982 {
983 size_t operator()(unsigned long x) const noexcept
984 {
985 return aux::hash(x);
986 }
987
988 using argument_type = unsigned long;
989 using result_type = size_t;
990 };
991
992 template<>
993 struct hash<unsigned long long>
994 {
995 size_t operator()(unsigned long long x) const noexcept
996 {
997 return aux::hash(x);
998 }
999
1000 using argument_type = unsigned long long;
1001 using result_type = size_t;
1002 };
1003
1004 template<>
1005 struct hash<float>
1006 {
1007 size_t operator()(float x) const noexcept
1008 {
1009 return aux::hash(x);
1010 }
1011
1012 using argument_type = float;
1013 using result_type = size_t;
1014 };
1015
1016 template<>
1017 struct hash<double>
1018 {
1019 size_t operator()(double x) const noexcept
1020 {
1021 return aux::hash(x);
1022 }
1023
1024 using argument_type = double;
1025 using result_type = size_t;
1026 };
1027
1028 template<>
1029 struct hash<long double>
1030 {
1031 size_t operator()(long double x) const noexcept
1032 {
1033 return aux::hash(x);
1034 }
1035
1036 using argument_type = long double;
1037 using result_type = size_t;
1038 };
1039
1040 template<class T>
1041 struct hash<T*>
1042 {
1043 size_t operator()(T* x) const noexcept
1044 {
1045 return aux::hash(x);
1046 }
1047
1048 using argument_type = T*;
1049 using result_type = size_t;
1050 };
1051}
1052
1053#endif
Note: See TracBrowser for help on using the repository browser.