xref: /llvm-project/libcxx/test/std/containers/unord/unord.multimap/unord.multimap.cnstr/deduct.pass.cpp (revision ef70fe4d264d20abdd8476605650479a96a62071)
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 
main(int,char **)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), std::end(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), std::end(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), std::end(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), std::end(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), std::end(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), std::end(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), std::end(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