source: mainline/uspace/lib/cpp/include/impl/functional.hpp@ 65dde99

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

cpp: added reference_wrapper

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