xref: /llvm-project/libcxx/test/std/containers/unord/unord.map/eq.different_hash.pass.cpp (revision 774295ca1d5ff752cb478b61f22a5b1dbe33074f)
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 // <unordered_map>
10 
11 // template <class Key, class T, class Hash, class Pred, class Alloc>
12 // bool
13 // operator==(const unordered_map<Key, T, Hash, Pred, Alloc>& x,
14 //            const unordered_map<Key, T, Hash, Pred, Alloc>& y);
15 //
16 // template <class Key, class T, class Hash, class Pred, class Alloc>
17 // bool
18 // operator!=(const unordered_map<Key, T, Hash, Pred, Alloc>& x,
19 //            const unordered_map<Key, T, Hash, Pred, Alloc>& y);
20 
21 // Implements paper: http://wg21.link/p0809
22 
23 #include <unordered_map>
24 #include <cstddef>
25 #include <limits>
26 #include <cassert>
27 #include <functional>
28 
29 template <class T>
hash_identity(T val)30 std::size_t hash_identity(T val) {
31   return val;
32 }
33 template <class T>
hash_neg(T val)34 std::size_t hash_neg(T val) {
35   return std::numeric_limits<T>::max() - val;
36 }
37 template <class T>
hash_scale(T val)38 std::size_t hash_scale(T val) {
39   return static_cast<std::size_t>(val << 1);
40 }
41 template <class T>
hash_even(T val)42 std::size_t hash_even(T val) {
43   return val & 1 ? 1 : 0;
44 }
45 template <class T>
hash_same(T)46 std::size_t hash_same(T /*val*/) {
47   return 1;
48 }
49 
50 template <class T>
hash_identity(T * val)51 std::size_t hash_identity(T* val) {
52   return *val;
53 }
54 template <class T>
hash_neg(T * val)55 std::size_t hash_neg(T* val) {
56   return std::numeric_limits<T>::max() - *val;
57 }
58 template <class T>
hash_scale(T * val)59 std::size_t hash_scale(T* val) {
60   return static_cast<std::size_t>(*val << 1);
61 }
62 template <class T>
hash_even(T * val)63 std::size_t hash_even(T* val) {
64   return *val & 1 ? 1 : 0;
65 }
66 
67 template <class Map, class Ittr>
populate(Map & m,Ittr start,Ittr end)68 void populate(Map& m, Ittr start, Ittr end) {
69   for (auto *p1 = start, *p2 = end - 1; p1 != end; ++p1, --p2) {
70     m.insert(std::make_pair(*p1, *p2));
71   }
72 }
73 
74 template <class T, std::size_t N>
test(T (& vals)[N])75 void test(T (&vals)[N]) {
76   using Hash = std::size_t (*)(T);
77   using C    = std::unordered_map<T, T, Hash, std::equal_to<T> >;
78 
79   C c1(0, hash_identity);
80   C c2(0, hash_neg);
81   C c3(0, hash_scale);
82   C c4(0, hash_even);
83   C c5(0, hash_same);
84 
85   populate(c1, std::begin(vals), std::end(vals));
86   populate(c2, std::begin(vals), std::end(vals));
87   populate(c3, std::begin(vals), std::end(vals));
88   populate(c4, std::begin(vals), std::end(vals));
89   populate(c5, std::begin(vals), std::end(vals));
90 
91   assert(c1 == c1);
92   assert(c1 == c2);
93   assert(c1 == c3);
94   assert(c1 == c4);
95   assert(c1 == c5);
96 
97   assert(c2 == c1);
98   assert(c2 == c2);
99   assert(c2 == c3);
100   assert(c2 == c4);
101   assert(c2 == c5);
102 
103   assert(c3 == c1);
104   assert(c3 == c2);
105   assert(c3 == c3);
106   assert(c3 == c4);
107   assert(c3 == c5);
108 
109   assert(c4 == c1);
110   assert(c4 == c2);
111   assert(c4 == c3);
112   assert(c4 == c4);
113   assert(c4 == c5);
114 
115   assert(c5 == c1);
116   assert(c5 == c2);
117   assert(c5 == c3);
118   assert(c5 == c4);
119   assert(c5 == c5);
120 }
121 
main(int,char **)122 int main(int, char**) {
123   {
124     std::size_t vals[] = {
125         // clang-format off
126         1,
127         2, 2,
128         3, 3, 3,
129         4, 4, 4, 4,
130         5, 5, 5, 5, 5,
131         6, 6, 6, 6, 6, 6,
132         7, 7, 7, 7, 7, 7, 7,
133         8, 8, 8, 8, 8, 8, 8, 8,
134         9, 9, 9, 9, 9, 9, 9, 9, 9,
135         10
136         // clang-format on
137     };
138     test(vals);
139   }
140 
141   {
142     bool vals[] = {true, false};
143     test(vals);
144   }
145 
146   {
147     char* vals[] = {(char*)("a"), (char*)("b"), (char*)("cde")};
148     test(vals);
149   }
150 
151   return 0;
152 }
153