source: mainline/uspace/lib/cpp/include/impl/functional.hpp@ 68cfab1

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

cpp: fixed a copy pasta error on the ONLY type I didn't test conditional typedefs on…

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