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 | // UNSUPPORTED: c++03, c++11, c++14 |
11 | |
12 | // template<class InputIterator, |
13 | // class Hash = hash<iter-key-type<InputIterator>>, |
14 | // class Pred = equal_to<iter-key-type<InputIterator>>, |
15 | // class Allocator = allocator<iter-to-alloc-type<InputIterator>>> |
16 | // unordered_multimap(InputIterator, InputIterator, typename see below::size_type = see below, |
17 | // Hash = Hash(), Pred = Pred(), Allocator = Allocator()) |
18 | // -> unordered_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash, Pred, |
19 | // Allocator>; |
20 | // |
21 | // template<class Key, class T, class Hash = hash<Key>, |
22 | // class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>> |
23 | // unordered_multimap(initializer_list<pair<Key, T>>, |
24 | // typename see below::size_type = see below, Hash = Hash(), |
25 | // Pred = Pred(), Allocator = Allocator()) |
26 | // -> unordered_multimap<Key, T, Hash, Pred, Allocator>; |
27 | // |
28 | // template<class InputIterator, class Allocator> |
29 | // unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Allocator) |
30 | // -> unordered_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, |
31 | // hash<iter-key-type<InputIterator>>, |
32 | // equal_to<iter-key-type<InputIterator>>, Allocator>; |
33 | // |
34 | // template<class InputIterator, class Allocator> |
35 | // unordered_multimap(InputIterator, InputIterator, Allocator) |
36 | // -> unordered_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, |
37 | // hash<iter-key-type<InputIterator>>, |
38 | // equal_to<iter-key-type<InputIterator>>, Allocator>; |
39 | // |
40 | // template<class InputIterator, class Hash, class Allocator> |
41 | // unordered_multimap(InputIterator, InputIterator, typename see below::size_type, Hash, Allocator) |
42 | // -> unordered_multimap<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, Hash, |
43 | // equal_to<iter-key-type<InputIterator>>, Allocator>; |
44 | // |
45 | // template<class Key, class T, class Allocator> |
46 | // unordered_multimap(initializer_list<pair<Key, T>>, typename see below::size_type, Allocator) |
47 | // -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>; |
48 | // |
49 | // template<class Key, class T, class Allocator> |
50 | // unordered_multimap(initializer_list<pair<Key, T>>, Allocator) |
51 | // -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>; |
52 | // |
53 | // template<class Key, class T, class Hash, class Allocator> |
54 | // unordered_multimap(initializer_list<pair<Key, T>>, typename see below::size_type, Hash, |
55 | // Allocator) |
56 | // -> unordered_multimap<Key, T, Hash, equal_to<Key>, Allocator>; |
57 | // |
58 | // template<ranges::input_range R, class Hash = hash<range-key-type<R>>, |
59 | // class Pred = equal_to<range-key-type<R>>, |
60 | // class Allocator = allocator<range-to-alloc-type<R>>> |
61 | // unordered_multimap(from_range_t, R&&, typename see below::size_type = see below, |
62 | // Hash = Hash(), Pred = Pred(), Allocator = Allocator()) |
63 | // -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, Hash, Pred, Allocator>; // C++23 |
64 | // |
65 | // template<ranges::input_range R, class Allocator> |
66 | // unordered_multimap(from_range_t, R&&, typename see below::size_type, Allocator) |
67 | // -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, hash<range-key-type<R>>, |
68 | // equal_to<range-key-type<R>>, Allocator>; // C++23 |
69 | // |
70 | // template<ranges::input_range R, class Allocator> |
71 | // unordered_multimap(from_range_t, R&&, Allocator) |
72 | // -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, hash<range-key-type<R>>, |
73 | // equal_to<range-key-type<R>>, Allocator>; // C++23 |
74 | // |
75 | // template<ranges::input_range R, class Hash, class Allocator> |
76 | // unordered_multimap(from_range_t, R&&, typename see below::size_type, Hash, Allocator) |
77 | // -> unordered_multimap<range-key-type<R>, range-mapped-type<R>, Hash, |
78 | // equal_to<range-key-type<R>>, Allocator>; // C++23 |
79 | |
80 | #include <algorithm> // is_permutation |
81 | #include <array> |
82 | #include <cassert> |
83 | #include <climits> // INT_MAX |
84 | #include <type_traits> |
85 | #include <unordered_map> |
86 | |
87 | #include "../../../test_compare.h" |
88 | #include "../../../test_hash.h" |
89 | #include "deduction_guides_sfinae_checks.h" |
90 | #include "test_allocator.h" |
91 | |
92 | using P = std::pair<int, long>; |
93 | using PC = std::pair<const int, long>; |
94 | |
95 | int main(int, char**) |
96 | { |
97 | const PC expected_m[] = { {1,1}, {1,1}, {2,2}, {3,1}, {INT_MAX,1} }; |
98 | |
99 | { |
100 | const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; |
101 | std::unordered_multimap m(std::begin(arr: arr), std::end(arr: arr)); |
102 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, long>); |
103 | assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); |
104 | } |
105 | |
106 | { |
107 | const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; |
108 | std::unordered_multimap m(std::begin(arr: arr), std::end(arr: arr), 42); |
109 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, long>); |
110 | assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); |
111 | } |
112 | |
113 | { |
114 | const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; |
115 | std::unordered_multimap m(std::begin(arr: arr), std::end(arr: arr), 42, std::hash<short>()); |
116 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, long, std::hash<short>, std::equal_to<int>>); |
117 | assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); |
118 | } |
119 | |
120 | { |
121 | const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; |
122 | std::unordered_multimap m(std::begin(arr: arr), std::end(arr: arr), 42, std::hash<short>(), std::equal_to<>()); |
123 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, long, std::hash<short>, std::equal_to<>>); |
124 | assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); |
125 | } |
126 | |
127 | { |
128 | const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; |
129 | std::unordered_multimap m(std::begin(arr: arr), std::end(arr: arr), 42, std::hash<short>(), std::equal_to<>(), test_allocator<PC>(0, 41)); |
130 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, long, std::hash<short>, std::equal_to<>, test_allocator<PC>>); |
131 | assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); |
132 | assert(m.get_allocator().get_id() == 41); |
133 | } |
134 | |
135 | { |
136 | std::unordered_multimap<int, long> source; |
137 | std::unordered_multimap m(source); |
138 | ASSERT_SAME_TYPE(decltype(m), decltype(source)); |
139 | assert(m.size() == 0); |
140 | } |
141 | |
142 | { |
143 | std::unordered_multimap<int, long> source; |
144 | std::unordered_multimap m{source}; // braces instead of parens |
145 | ASSERT_SAME_TYPE(decltype(m), decltype(source)); |
146 | assert(m.size() == 0); |
147 | } |
148 | |
149 | { |
150 | std::unordered_multimap<int, long, std::hash<short>, std::equal_to<>, test_allocator<PC>> source; |
151 | test_allocator<PC> a(0, 42); |
152 | std::unordered_multimap m(source, a); |
153 | ASSERT_SAME_TYPE(decltype(m), decltype(source)); |
154 | assert(m.get_allocator().get_id() == 42); |
155 | assert(m.size() == 0); |
156 | } |
157 | |
158 | { |
159 | std::unordered_multimap<int, long, std::hash<short>, std::equal_to<>, test_allocator<PC>> source; |
160 | test_allocator<PC> a(0, 43); |
161 | std::unordered_multimap m{source, a}; // braces instead of parens |
162 | ASSERT_SAME_TYPE(decltype(m), decltype(source)); |
163 | assert(m.get_allocator().get_id() == 43); |
164 | assert(m.size() == 0); |
165 | } |
166 | |
167 | { |
168 | std::unordered_multimap m { P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }; |
169 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, long>); |
170 | assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); |
171 | } |
172 | |
173 | { |
174 | std::unordered_multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42); |
175 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, long>); |
176 | assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); |
177 | } |
178 | |
179 | { |
180 | std::unordered_multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, std::hash<short>()); |
181 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, long, std::hash<short>>); |
182 | assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); |
183 | } |
184 | |
185 | { |
186 | std::unordered_multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, std::hash<short>(), std::equal_to<>()); |
187 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, long, std::hash<short>, std::equal_to<>>); |
188 | assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); |
189 | } |
190 | |
191 | { |
192 | std::unordered_multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, std::hash<short>(), std::equal_to<>(), test_allocator<PC>(0, 44)); |
193 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, long, std::hash<short>, std::equal_to<>, test_allocator<PC>>); |
194 | assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); |
195 | assert(m.get_allocator().get_id() == 44); |
196 | } |
197 | |
198 | { |
199 | const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; |
200 | std::unordered_multimap m(std::begin(arr: arr), std::end(arr: arr), 42, test_allocator<PC>(0, 45)); |
201 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, long, std::hash<int>, std::equal_to<int>, test_allocator<PC>>); |
202 | assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); |
203 | assert(m.get_allocator().get_id() == 45); |
204 | } |
205 | |
206 | { |
207 | const P arr[] = { {1,1}, {2,2}, {1,1}, {INT_MAX,1}, {3,1} }; |
208 | std::unordered_multimap m(std::begin(arr: arr), std::end(arr: arr), 42, std::hash<short>(), test_allocator<PC>(0, 46)); |
209 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, long, std::hash<short>, std::equal_to<int>, test_allocator<PC>>); |
210 | assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); |
211 | assert(m.get_allocator().get_id() == 46); |
212 | } |
213 | |
214 | { |
215 | std::unordered_multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, test_allocator<PC>(0, 47)); |
216 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, long, std::hash<int>, std::equal_to<int>, test_allocator<PC>>); |
217 | assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); |
218 | assert(m.get_allocator().get_id() == 47); |
219 | } |
220 | |
221 | { |
222 | std::unordered_multimap m({ P{1,1L}, P{2,2L}, P{1,1L}, P{INT_MAX,1L}, P{3,1L} }, 42, std::hash<short>(), test_allocator<PC>(0, 48)); |
223 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, long, std::hash<short>, std::equal_to<int>, test_allocator<PC>>); |
224 | assert(std::is_permutation(m.begin(), m.end(), std::begin(expected_m), std::end(expected_m))); |
225 | assert(m.get_allocator().get_id() == 48); |
226 | } |
227 | |
228 | { |
229 | // Examples from LWG3025 |
230 | std::unordered_multimap m{std::pair{1, 1}, {2, 2}, {3, 3}}; |
231 | ASSERT_SAME_TYPE(decltype(m), std::unordered_multimap<int, int>); |
232 | |
233 | std::unordered_multimap m2{m.begin(), m.end()}; |
234 | ASSERT_SAME_TYPE(decltype(m2), std::unordered_multimap<int, int>); |
235 | } |
236 | |
237 | { |
238 | // Examples from LWG3531 |
239 | std::unordered_multimap m1{{std::pair{1, 2}, {3, 4}}, 0}; |
240 | ASSERT_SAME_TYPE(decltype(m1), std::unordered_multimap<int, int>); |
241 | |
242 | using value_type = std::pair<const int, int>; |
243 | std::unordered_multimap m2{{value_type{1, 2}, {3, 4}}, 0}; |
244 | ASSERT_SAME_TYPE(decltype(m2), std::unordered_multimap<int, int>); |
245 | } |
246 | |
247 | #if TEST_STD_VER >= 23 |
248 | { |
249 | using Range = std::array<P, 0>; |
250 | using Pred = test_equal_to<int>; |
251 | using DefaultPred = std::equal_to<int>; |
252 | using Hash = test_hash<int>; |
253 | using DefaultHash = std::hash<int>; |
254 | using Alloc = test_allocator<PC>; |
255 | |
256 | { // (from_range, range) |
257 | std::unordered_multimap c(std::from_range, Range()); |
258 | static_assert(std::is_same_v<decltype(c), std::unordered_multimap<int, long>>); |
259 | } |
260 | |
261 | { // (from_range, range, n) |
262 | std::unordered_multimap c(std::from_range, Range(), std::size_t()); |
263 | static_assert(std::is_same_v<decltype(c), std::unordered_multimap<int, long>>); |
264 | } |
265 | |
266 | { // (from_range, range, n, hash) |
267 | std::unordered_multimap c(std::from_range, Range(), std::size_t(), Hash()); |
268 | static_assert(std::is_same_v<decltype(c), std::unordered_multimap<int, long, Hash>>); |
269 | } |
270 | |
271 | { // (from_range, range, n, hash, pred) |
272 | std::unordered_multimap c(std::from_range, Range(), std::size_t(), Hash(), Pred()); |
273 | static_assert(std::is_same_v<decltype(c), std::unordered_multimap<int, long, Hash, Pred>>); |
274 | } |
275 | |
276 | { // (from_range, range, n, hash, pred, alloc) |
277 | std::unordered_multimap c(std::from_range, Range(), std::size_t(), Hash(), Pred(), Alloc()); |
278 | static_assert(std::is_same_v<decltype(c), std::unordered_multimap<int, long, Hash, Pred, Alloc>>); |
279 | } |
280 | |
281 | { // (from_range, range, n, alloc) |
282 | std::unordered_multimap c(std::from_range, Range(), std::size_t(), Alloc()); |
283 | static_assert(std::is_same_v<decltype(c), std::unordered_multimap<int, long, DefaultHash, DefaultPred, Alloc>>); |
284 | } |
285 | |
286 | // TODO(LWG 2713): uncomment this test once the constructor is added. |
287 | { // (from_range, range, alloc) |
288 | //std::unordered_multimap c(std::from_range, Range(), Alloc()); |
289 | //static_assert(std::is_same_v<decltype(c), std::unordered_multimap<int, long, DefaultHash, DefaultPred, Alloc>>); |
290 | } |
291 | |
292 | { // (from_range, range, n, hash, alloc) |
293 | std::unordered_multimap c(std::from_range, Range(), std::size_t(), Hash(), Alloc()); |
294 | static_assert(std::is_same_v<decltype(c), std::unordered_multimap<int, long, Hash, DefaultPred, Alloc>>); |
295 | } |
296 | } |
297 | #endif |
298 | |
299 | UnorderedContainerDeductionGuidesSfinaeAway<std::unordered_multimap, std::unordered_multimap<int, long>>(); |
300 | |
301 | return 0; |
302 | } |
303 | |