xref: /llvm-project/libcxx/test/std/containers/unord/unord.multiset/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_set>
10 
11 // template <class Key, class T, class Hash, class Pred, class Alloc>
12 // bool
13 // operator==(const unordered_multiset<Key, T, Hash, Pred, Alloc>& x,
14 //            const unordered_multiset<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_multiset<Key, T, Hash, Pred, Alloc>& x,
19 //            const unordered_multiset<Key, T, Hash, Pred, Alloc>& y);
20 
21 // Implements paper: http://wg21.link/p0809
22 
23 #include <cassert>
24 #include <cstddef>
25 #include <functional>
26 #include <limits>
27 #include <unordered_set>
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 T, std::size_t N>
test(T (& vals)[N])68 void test(T (&vals)[N]) {
69   using Hash = std::size_t (*)(T);
70   using C    = std::unordered_multiset<T, Hash, std::equal_to<T> >;
71 
72   C c1(std::begin(vals), std::end(vals), 0, hash_identity);
73   C c2(std::begin(vals), std::end(vals), 0, hash_neg);
74   C c3(std::begin(vals), std::end(vals), 0, hash_scale);
75   C c4(std::begin(vals), std::end(vals), 0, hash_even);
76   C c5(std::begin(vals), std::end(vals), 0, hash_same);
77 
78   assert(c1 == c1);
79   assert(c1 == c2);
80   assert(c1 == c3);
81   assert(c1 == c4);
82   assert(c1 == c5);
83 
84   assert(c2 == c1);
85   assert(c2 == c2);
86   assert(c2 == c3);
87   assert(c2 == c4);
88   assert(c2 == c5);
89 
90   assert(c3 == c1);
91   assert(c3 == c2);
92   assert(c3 == c3);
93   assert(c3 == c4);
94   assert(c3 == c5);
95 
96   assert(c4 == c1);
97   assert(c4 == c2);
98   assert(c4 == c3);
99   assert(c4 == c4);
100   assert(c4 == c5);
101 
102   assert(c5 == c1);
103   assert(c5 == c2);
104   assert(c5 == c3);
105   assert(c5 == c4);
106   assert(c5 == c5);
107 }
108 
main(int,char **)109 int main(int, char**) {
110   {
111     std::size_t vals[] = {
112         // clang-format off
113         1,
114         2, 2,
115         3, 3, 3,
116         4, 4, 4, 4,
117         5, 5, 5, 5, 5,
118         6, 6, 6, 6, 6, 6,
119         7, 7, 7, 7, 7, 7, 7,
120         8, 8, 8, 8, 8, 8, 8, 8,
121         9, 9, 9, 9, 9, 9, 9, 9, 9,
122         10
123         // clang-format on
124     };
125     test(vals);
126   }
127   {
128     bool vals[] = {true, false};
129     test(vals);
130   }
131   {
132     char* vals[] = {(char*)("a"), (char*)("b"), (char*)("cde")};
133     test(vals);
134   }
135 
136   return 0;
137 }
138