1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // <memory>
10 
11 // template <class T, class D>
12 // struct hash<unique_ptr<T, D>>
13 // {
14 //     typedef unique_ptr<T, D> argument_type;
15 //     typedef size_t           result_type;
16 //     size_t operator()(const unique_ptr<T, D>& p) const;
17 // };
18 
19 #include <memory>
20 
21 #include <cassert>
22 #include <functional>
23 
24 #include "test_macros.h"
25 
26 #if TEST_STD_VER >= 11
27 #include "poisoned_hash_helper.h"
28 #include "deleter_types.h"
29 #include "min_allocator.h"
30 
31 template <class ValueT, class Del>
32 void test_enabled_with_deleter() {
33   using UPtr = std::unique_ptr<ValueT, Del>;
34   using pointer = typename UPtr::pointer;
35   using RawDel = typename std::decay<Del>::type;
36   RawDel d(1);
37   UPtr p(nullptr, std::forward<Del>(d));
38   test_hash_enabled<UPtr>(p);
39   test_hash_enabled<pointer>();
40 }
41 
42 template <class ValueT, class Del>
43 void test_disabled_with_deleter() {
44   using UPtr = std::unique_ptr<ValueT, Del>;
45   using pointer = typename UPtr::pointer;
46   test_hash_disabled<UPtr>();
47   test_hash_disabled<pointer>();
48 }
49 
50 template <class T>
51 struct std::hash<min_pointer<T, std::integral_constant<std::size_t, 1>>> {
52   std::size_t operator()(min_pointer<T, std::integral_constant<size_t, 1>> p) const TEST_NOEXCEPT_FALSE {
53     if (!p) return 0;
54     return std::hash<T*>{}(std::addressof(*p));
55   }
56 };
57 
58 struct A {};
59 
60 #endif // TEST_STD_VER >= 11
61 
62 int main(int, char**)
63 {
64   {
65     int* ptr = new int;
66     std::unique_ptr<int> p(ptr);
67     std::hash<std::unique_ptr<int> > f;
68     std::size_t h = f(p);
69     assert(h == std::hash<int*>()(ptr));
70   }
71 #if TEST_STD_VER >= 11
72   {
73     std::unique_ptr<int, PointerDeleter<int, 1>> pThrowingHash;
74     std::hash<std::unique_ptr<int, PointerDeleter<int, 1>>> fThrowingHash;
75     ASSERT_NOT_NOEXCEPT(fThrowingHash(pThrowingHash));
76   }
77   {
78     test_enabled_with_deleter<int, Deleter<int>>();
79     test_enabled_with_deleter<int[], Deleter<int[]>>();
80     test_enabled_with_deleter<int, CopyDeleter<int>>();
81     test_enabled_with_deleter<int, CopyDeleter<int[]>>();
82     test_enabled_with_deleter<int, NCDeleter<int>&>();
83     test_enabled_with_deleter<int[], NCDeleter<int[]>&>();
84     test_enabled_with_deleter<int, NCConstDeleter<int> const&>();
85     test_enabled_with_deleter<int[], NCConstDeleter<int[]> const&>();
86   }
87   {
88     test_enabled_with_deleter<int, PointerDeleter<int, 1>>();
89     test_enabled_with_deleter<int[], PointerDeleter<int[], 1>>();
90     test_enabled_with_deleter<A, PointerDeleter<A, 1>>();
91     test_enabled_with_deleter<A[], PointerDeleter<A[], 1>>();
92 
93 #if TEST_STD_VER > 14
94     test_disabled_with_deleter<int, PointerDeleter<int, 0>>();
95     test_disabled_with_deleter<int[], PointerDeleter<int[], 0>>();
96     test_disabled_with_deleter<A, PointerDeleter<A, 0>>();
97     test_disabled_with_deleter<A[], PointerDeleter<A[], 0>>();
98 #endif
99   }
100 #endif
101 
102   return 0;
103 }
104