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 = hash<Key>, class Pred = equal_to<Key>, |
12 | // class Alloc = allocator<pair<const Key, T>>> |
13 | // class unordered_multimap |
14 | |
15 | // unordered_multimap& operator=(const unordered_multimap& u); |
16 | |
17 | #include <unordered_map> |
18 | #include <string> |
19 | #include <set> |
20 | #include <cassert> |
21 | #include <cfloat> |
22 | #include <cmath> |
23 | #include <algorithm> |
24 | #include <cstddef> |
25 | |
26 | #include "test_macros.h" |
27 | #include "../../../check_consecutive.h" |
28 | #include "../../../test_compare.h" |
29 | #include "../../../test_hash.h" |
30 | #include "test_allocator.h" |
31 | #include "min_allocator.h" |
32 | |
33 | int main(int, char**) |
34 | { |
35 | { |
36 | typedef test_allocator<std::pair<const int, std::string> > A; |
37 | typedef std::unordered_multimap<int, std::string, |
38 | test_hash<int>, |
39 | test_equal_to<int>, |
40 | A |
41 | > C; |
42 | typedef std::pair<int, std::string> P; |
43 | P a[] = |
44 | { |
45 | P(1, "one" ), |
46 | P(2, "two" ), |
47 | P(3, "three" ), |
48 | P(4, "four" ), |
49 | P(1, "four" ), |
50 | P(2, "four" ), |
51 | }; |
52 | C c0(a, a + sizeof(a)/sizeof(a[0]), |
53 | 7, |
54 | test_hash<int>(8), |
55 | test_equal_to<int>(9), |
56 | A(10) |
57 | ); |
58 | C c(a, a + 2, |
59 | 7, |
60 | test_hash<int>(2), |
61 | test_equal_to<int>(3), |
62 | A(4) |
63 | ); |
64 | c = c0; |
65 | LIBCPP_ASSERT(c.bucket_count() == 7); |
66 | assert(c.size() == 6); |
67 | std::multiset<std::string> s; |
68 | s.insert(x: "one" ); |
69 | s.insert(x: "four" ); |
70 | CheckConsecutiveKeys<C::const_iterator>(pos: c.find(x: 1), end: c.end(), key: 1, values&: s); |
71 | s.insert(x: "two" ); |
72 | s.insert(x: "four" ); |
73 | CheckConsecutiveKeys<C::const_iterator>(pos: c.find(x: 2), end: c.end(), key: 2, values&: s); |
74 | s.insert(x: "three" ); |
75 | CheckConsecutiveKeys<C::const_iterator>(pos: c.find(x: 3), end: c.end(), key: 3, values&: s); |
76 | s.insert(x: "four" ); |
77 | CheckConsecutiveKeys<C::const_iterator>(pos: c.find(x: 4), end: c.end(), key: 4, values&: s); |
78 | assert(c.hash_function() == test_hash<int>(8)); |
79 | assert(c.key_eq() == test_equal_to<int>(9)); |
80 | assert(c.get_allocator() == A(4)); |
81 | assert(!c.empty()); |
82 | assert(static_cast<std::size_t>(std::distance(c.begin(), c.end())) == c.size()); |
83 | assert(static_cast<std::size_t>(std::distance(c.cbegin(), c.cend())) == c.size()); |
84 | assert(fabs(c.load_factor() - (float)c.size()/c.bucket_count()) < FLT_EPSILON); |
85 | assert(c.max_load_factor() == 1); |
86 | } |
87 | { |
88 | typedef std::unordered_multimap<int, std::string> C; |
89 | typedef std::pair<const int, std::string> P; |
90 | const P a[] = |
91 | { |
92 | P(1, "one" ), |
93 | P(2, "two" ), |
94 | P(3, "three" ), |
95 | P(4, "four" ), |
96 | P(1, "four" ), |
97 | P(2, "four" ), |
98 | }; |
99 | C c(a, a+sizeof(a)/sizeof(a[0])); |
100 | C *p = &c; |
101 | c = *p; |
102 | assert(c.size() == 6); |
103 | assert(std::is_permutation(c.begin(), c.end(), a)); |
104 | } |
105 | { |
106 | typedef other_allocator<std::pair<const int, std::string> > A; |
107 | typedef std::unordered_multimap<int, std::string, |
108 | test_hash<int>, |
109 | test_equal_to<int>, |
110 | A |
111 | > C; |
112 | typedef std::pair<int, std::string> P; |
113 | P a[] = |
114 | { |
115 | P(1, "one" ), |
116 | P(2, "two" ), |
117 | P(3, "three" ), |
118 | P(4, "four" ), |
119 | P(1, "four" ), |
120 | P(2, "four" ), |
121 | }; |
122 | C c0(a, a + sizeof(a)/sizeof(a[0]), |
123 | 7, |
124 | test_hash<int>(8), |
125 | test_equal_to<int>(9), |
126 | A(10) |
127 | ); |
128 | C c(a, a + 2, |
129 | 7, |
130 | test_hash<int>(2), |
131 | test_equal_to<int>(3), |
132 | A(4) |
133 | ); |
134 | c = c0; |
135 | assert(c.bucket_count() >= 7); |
136 | assert(c.size() == 6); |
137 | std::multiset<std::string> s; |
138 | s.insert(x: "one" ); |
139 | s.insert(x: "four" ); |
140 | CheckConsecutiveKeys<C::const_iterator>(pos: c.find(x: 1), end: c.end(), key: 1, values&: s); |
141 | s.insert(x: "two" ); |
142 | s.insert(x: "four" ); |
143 | CheckConsecutiveKeys<C::const_iterator>(pos: c.find(x: 2), end: c.end(), key: 2, values&: s); |
144 | s.insert(x: "three" ); |
145 | CheckConsecutiveKeys<C::const_iterator>(pos: c.find(x: 3), end: c.end(), key: 3, values&: s); |
146 | s.insert(x: "four" ); |
147 | CheckConsecutiveKeys<C::const_iterator>(pos: c.find(x: 4), end: c.end(), key: 4, values&: s); |
148 | assert(c.hash_function() == test_hash<int>(8)); |
149 | assert(c.key_eq() == test_equal_to<int>(9)); |
150 | assert(c.get_allocator() == A(10)); |
151 | assert(!c.empty()); |
152 | assert(static_cast<std::size_t>(std::distance(c.begin(), c.end())) == c.size()); |
153 | assert(static_cast<std::size_t>(std::distance(c.cbegin(), c.cend())) == c.size()); |
154 | assert(fabs(c.load_factor() - (float)c.size()/c.bucket_count()) < FLT_EPSILON); |
155 | assert(c.max_load_factor() == 1); |
156 | } |
157 | #if TEST_STD_VER >= 11 |
158 | { |
159 | typedef min_allocator<std::pair<const int, std::string> > A; |
160 | typedef std::unordered_multimap<int, std::string, |
161 | test_hash<int>, |
162 | test_equal_to<int>, |
163 | A |
164 | > C; |
165 | typedef std::pair<int, std::string> P; |
166 | P a[] = |
167 | { |
168 | P(1, "one" ), |
169 | P(2, "two" ), |
170 | P(3, "three" ), |
171 | P(4, "four" ), |
172 | P(1, "four" ), |
173 | P(2, "four" ), |
174 | }; |
175 | C c0(a, a + sizeof(a)/sizeof(a[0]), |
176 | 7, |
177 | test_hash<int>(8), |
178 | test_equal_to<int>(9), |
179 | A() |
180 | ); |
181 | C c(a, a + 2, |
182 | 7, |
183 | test_hash<int>(2), |
184 | test_equal_to<int>(3), |
185 | A() |
186 | ); |
187 | c = c0; |
188 | LIBCPP_ASSERT(c.bucket_count() == 7); |
189 | assert(c.size() == 6); |
190 | std::multiset<std::string> s; |
191 | s.insert("one" ); |
192 | s.insert("four" ); |
193 | CheckConsecutiveKeys<C::const_iterator>(c.find(1), c.end(), 1, s); |
194 | s.insert("two" ); |
195 | s.insert("four" ); |
196 | CheckConsecutiveKeys<C::const_iterator>(c.find(2), c.end(), 2, s); |
197 | s.insert("three" ); |
198 | CheckConsecutiveKeys<C::const_iterator>(c.find(3), c.end(), 3, s); |
199 | s.insert("four" ); |
200 | CheckConsecutiveKeys<C::const_iterator>(c.find(4), c.end(), 4, s); |
201 | assert(c.hash_function() == test_hash<int>(8)); |
202 | assert(c.key_eq() == test_equal_to<int>(9)); |
203 | assert(c.get_allocator() == A()); |
204 | assert(!c.empty()); |
205 | assert(static_cast<std::size_t>(std::distance(c.begin(), c.end())) == c.size()); |
206 | assert(static_cast<std::size_t>(std::distance(c.cbegin(), c.cend())) == c.size()); |
207 | assert(fabs(c.load_factor() - (float)c.size()/c.bucket_count()) < FLT_EPSILON); |
208 | assert(c.max_load_factor() == 1); |
209 | } |
210 | #endif |
211 | |
212 | return 0; |
213 | } |
214 | |