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