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 // <map>
10
11 // class map
12
13 // map& operator=(const map& m);
14
15 // XFAIL: libcpp-has-debug-mode
16
17 #include <map>
18 #include <algorithm>
19 #include <cassert>
20 #include <cstdio>
21 #include <iterator>
22 #include <vector>
23
24 #include "test_macros.h"
25 #include "../../../test_compare.h"
26 #include "test_allocator.h"
27 #include "min_allocator.h"
28
29 #if TEST_STD_VER >= 11
30 std::vector<int> ca_allocs;
31 std::vector<int> ca_deallocs;
32
33 template <class T>
34 class counting_allocatorT {
35 public:
36 typedef T value_type;
37 int foo{0};
counting_allocatorT(int f)38 counting_allocatorT(int f) noexcept : foo(f) {}
39
40 using propagate_on_container_copy_assignment = std::true_type;
counting_allocatorT(const counting_allocatorT<U> & other)41 template <class U> counting_allocatorT(const counting_allocatorT<U>& other) noexcept {foo = other.foo;}
operator ==(const counting_allocatorT<U> & other) const42 template <class U> bool operator==(const counting_allocatorT<U>& other) const noexcept { return foo == other.foo; }
operator !=(const counting_allocatorT<U> & other) const43 template <class U> bool operator!=(const counting_allocatorT<U>& other) const noexcept { return foo != other.foo; }
44
allocate(size_t n) const45 T* allocate(size_t n) const {
46 ca_allocs.push_back(foo);
47 void * const pv = ::malloc(n * sizeof(T));
48 return static_cast<T *>(pv);
49 }
deallocate(T * p,size_t) const50 void deallocate(T* p, size_t) const noexcept {
51 ca_deallocs.push_back(foo);
52 free(p);
53 }
54 };
55
56 template <class T>
57 class counting_allocatorF {
58 public:
59 typedef T value_type;
60 int foo{0};
counting_allocatorF(int f)61 counting_allocatorF(int f) noexcept : foo(f) {}
62
63 using propagate_on_container_copy_assignment = std::false_type;
counting_allocatorF(const counting_allocatorF<U> & other)64 template <class U> counting_allocatorF(const counting_allocatorF<U>& other) noexcept {foo = other.foo;}
operator ==(const counting_allocatorF<U> & other) const65 template <class U> bool operator==(const counting_allocatorF<U>& other) const noexcept { return foo == other.foo; }
operator !=(const counting_allocatorF<U> & other) const66 template <class U> bool operator!=(const counting_allocatorF<U>& other) const noexcept { return foo != other.foo; }
67
allocate(size_t n) const68 T* allocate(size_t n) const {
69 ca_allocs.push_back(foo);
70 void * const pv = ::malloc(n * sizeof(T));
71 return static_cast<T *>(pv);
72 }
deallocate(T * p,size_t) const73 void deallocate(T* p, size_t) const noexcept {
74 ca_deallocs.push_back(foo);
75 free(p);
76 }
77 };
78
balanced_allocs()79 bool balanced_allocs() {
80 std::vector<int> temp1, temp2;
81
82 std::printf("Allocations = %zu, deallocations = %zu\n", ca_allocs.size(),
83 ca_deallocs.size());
84 if (ca_allocs.size() != ca_deallocs.size())
85 return false;
86
87 temp1 = ca_allocs;
88 std::sort(temp1.begin(), temp1.end());
89 temp2.clear();
90 std::unique_copy(temp1.begin(), temp1.end(), std::back_inserter<std::vector<int>>(temp2));
91 std::printf("There were %zu different allocators\n", temp2.size());
92
93 for (std::vector<int>::const_iterator it = temp2.begin(); it != temp2.end(); ++it ) {
94 std::ptrdiff_t const allocs = std::count(ca_allocs.begin(), ca_allocs.end(), *it);
95 std::ptrdiff_t const deallocs = std::count(ca_deallocs.begin(), ca_deallocs.end(), *it);
96 std::printf("%d: %td vs %td\n", *it, allocs, deallocs);
97 if (allocs != deallocs)
98 return false;
99 }
100
101 temp1 = ca_allocs;
102 std::sort(temp1.begin(), temp1.end());
103 temp2.clear();
104 std::unique_copy(temp1.begin(), temp1.end(), std::back_inserter<std::vector<int>>(temp2));
105 std::printf("There were %zu different (de)allocators\n", temp2.size());
106
107 for (std::vector<int>::const_iterator it = ca_deallocs.begin(); it != ca_deallocs.end(); ++it ) {
108 std::ptrdiff_t const allocs = std::count(ca_allocs.begin(), ca_allocs.end(), *it);
109 std::ptrdiff_t const deallocs = std::count(ca_deallocs.begin(), ca_deallocs.end(), *it);
110 std::printf("%d: %td vs %td\n", *it, allocs, deallocs);
111 if (allocs != deallocs)
112 return false;
113 }
114
115 return true;
116 }
117 #endif
118
main(int,char **)119 int main(int, char**)
120 {
121 {
122 typedef std::pair<const int, double> V;
123 V ar[] =
124 {
125 V(1, 1),
126 V(1, 1.5),
127 V(1, 2),
128 V(2, 1),
129 V(2, 1.5),
130 V(2, 2),
131 V(3, 1),
132 V(3, 1.5),
133 V(3, 2)
134 };
135 typedef test_less<int> C;
136 typedef test_allocator<V> A;
137 std::map<int, double, C, A> mo(ar, ar+sizeof(ar)/sizeof(ar[0]), C(5), A(2));
138 std::map<int, double, C, A> m(ar, ar+sizeof(ar)/sizeof(ar[0])/2, C(3), A(7));
139 m = mo;
140 assert(m.get_allocator() == A(7));
141 assert(m.key_comp() == C(5));
142 assert(m.size() == 3);
143 assert(std::distance(m.begin(), m.end()) == 3);
144 assert(*m.begin() == V(1, 1));
145 assert(*std::next(m.begin()) == V(2, 1));
146 assert(*std::next(m.begin(), 2) == V(3, 1));
147
148 assert(mo.get_allocator() == A(2));
149 assert(mo.key_comp() == C(5));
150 assert(mo.size() == 3);
151 assert(std::distance(mo.begin(), mo.end()) == 3);
152 assert(*mo.begin() == V(1, 1));
153 assert(*std::next(mo.begin()) == V(2, 1));
154 assert(*std::next(mo.begin(), 2) == V(3, 1));
155 }
156 {
157 typedef std::pair<const int, double> V;
158 const V ar[] =
159 {
160 V(1, 1),
161 V(2, 1),
162 V(3, 1),
163 };
164 std::map<int, double> m(ar, ar+sizeof(ar)/sizeof(ar[0]));
165 std::map<int, double> *p = &m;
166 m = *p;
167
168 assert(m.size() == 3);
169 assert(std::equal(m.begin(), m.end(), ar));
170 }
171 {
172 typedef std::pair<const int, double> V;
173 V ar[] =
174 {
175 V(1, 1),
176 V(1, 1.5),
177 V(1, 2),
178 V(2, 1),
179 V(2, 1.5),
180 V(2, 2),
181 V(3, 1),
182 V(3, 1.5),
183 V(3, 2)
184 };
185 typedef test_less<int> C;
186 typedef other_allocator<V> A;
187 std::map<int, double, C, A> mo(ar, ar+sizeof(ar)/sizeof(ar[0]), C(5), A(2));
188 std::map<int, double, C, A> m(ar, ar+sizeof(ar)/sizeof(ar[0])/2, C(3), A(7));
189 m = mo;
190 assert(m.get_allocator() == A(2));
191 assert(m.key_comp() == C(5));
192 assert(m.size() == 3);
193 assert(std::distance(m.begin(), m.end()) == 3);
194 assert(*m.begin() == V(1, 1));
195 assert(*std::next(m.begin()) == V(2, 1));
196 assert(*std::next(m.begin(), 2) == V(3, 1));
197
198 assert(mo.get_allocator() == A(2));
199 assert(mo.key_comp() == C(5));
200 assert(mo.size() == 3);
201 assert(std::distance(mo.begin(), mo.end()) == 3);
202 assert(*mo.begin() == V(1, 1));
203 assert(*std::next(mo.begin()) == V(2, 1));
204 assert(*std::next(mo.begin(), 2) == V(3, 1));
205 }
206 #if TEST_STD_VER >= 11
207 {
208 typedef std::pair<const int, double> V;
209 V ar[] =
210 {
211 V(1, 1),
212 V(1, 1.5),
213 V(1, 2),
214 V(2, 1),
215 V(2, 1.5),
216 V(2, 2),
217 V(3, 1),
218 V(3, 1.5),
219 V(3, 2)
220 };
221 typedef test_less<int> C;
222 typedef min_allocator<V> A;
223 std::map<int, double, C, A> mo(ar, ar+sizeof(ar)/sizeof(ar[0]), C(5), A());
224 std::map<int, double, C, A> m(ar, ar+sizeof(ar)/sizeof(ar[0])/2, C(3), A());
225 m = mo;
226 assert(m.get_allocator() == A());
227 assert(m.key_comp() == C(5));
228 assert(m.size() == 3);
229 assert(std::distance(m.begin(), m.end()) == 3);
230 assert(*m.begin() == V(1, 1));
231 assert(*std::next(m.begin()) == V(2, 1));
232 assert(*std::next(m.begin(), 2) == V(3, 1));
233
234 assert(mo.get_allocator() == A());
235 assert(mo.key_comp() == C(5));
236 assert(mo.size() == 3);
237 assert(std::distance(mo.begin(), mo.end()) == 3);
238 assert(*mo.begin() == V(1, 1));
239 assert(*std::next(mo.begin()) == V(2, 1));
240 assert(*std::next(mo.begin(), 2) == V(3, 1));
241 }
242 {
243 typedef std::pair<const int, double> V;
244 V ar[] =
245 {
246 V(1, 1),
247 V(1, 1.5),
248 V(1, 2),
249 V(2, 1),
250 V(2, 1.5),
251 V(2, 2),
252 V(3, 1),
253 V(3, 1.5),
254 V(3, 2)
255 };
256 typedef test_less<int> C;
257 typedef min_allocator<V> A;
258 std::map<int, double, C, A> mo(ar, ar+sizeof(ar)/sizeof(ar[0]), C(5), A());
259 std::map<int, double, C, A> m(ar, ar+sizeof(ar)/sizeof(ar[0])/2, C(3), A());
260 m = mo;
261 assert(m.get_allocator() == A());
262 assert(m.key_comp() == C(5));
263 assert(m.size() == 3);
264 assert(std::distance(m.begin(), m.end()) == 3);
265 assert(*m.begin() == V(1, 1));
266 assert(*std::next(m.begin()) == V(2, 1));
267 assert(*std::next(m.begin(), 2) == V(3, 1));
268
269 assert(mo.get_allocator() == A());
270 assert(mo.key_comp() == C(5));
271 assert(mo.size() == 3);
272 assert(std::distance(mo.begin(), mo.end()) == 3);
273 assert(*mo.begin() == V(1, 1));
274 assert(*std::next(mo.begin()) == V(2, 1));
275 assert(*std::next(mo.begin(), 2) == V(3, 1));
276 }
277
278 assert(balanced_allocs());
279 {
280 typedef std::pair<const int, double> V;
281 V ar[] =
282 {
283 V(1, 1),
284 V(1, 1.5),
285 V(1, 2),
286 V(2, 1),
287 V(2, 1.5),
288 V(2, 2),
289 V(3, 1),
290 V(3, 1.5),
291 V(3, 2)
292 };
293 typedef test_less<int> C;
294 typedef counting_allocatorT<V> A;
295 std::map<int, double, C, A> mo(ar, ar+sizeof(ar)/sizeof(ar[0]), C(5), A(1));
296 std::map<int, double, C, A> m(ar, ar+sizeof(ar)/sizeof(ar[0])/2, C(3), A(2));
297 m = mo;
298 assert(m.key_comp() == C(5));
299 assert(m.size() == 3);
300 assert(std::distance(m.begin(), m.end()) == 3);
301 assert(*m.begin() == V(1, 1));
302 assert(*std::next(m.begin()) == V(2, 1));
303 assert(*std::next(m.begin(), 2) == V(3, 1));
304
305 assert(mo.key_comp() == C(5));
306 assert(mo.size() == 3);
307 assert(std::distance(mo.begin(), mo.end()) == 3);
308 assert(*mo.begin() == V(1, 1));
309 assert(*std::next(mo.begin()) == V(2, 1));
310 assert(*std::next(mo.begin(), 2) == V(3, 1));
311 }
312 assert(balanced_allocs());
313 {
314 typedef std::pair<const int, double> V;
315 V ar[] =
316 {
317 V(1, 1),
318 V(1, 1.5),
319 V(1, 2),
320 V(2, 1),
321 V(2, 1.5),
322 V(2, 2),
323 V(3, 1),
324 V(3, 1.5),
325 V(3, 2)
326 };
327 typedef test_less<int> C;
328 typedef counting_allocatorF<V> A;
329 std::map<int, double, C, A> mo(ar, ar+sizeof(ar)/sizeof(ar[0]), C(5), A(100));
330 std::map<int, double, C, A> m(ar, ar+sizeof(ar)/sizeof(ar[0])/2, C(3), A(200));
331 m = mo;
332 assert(m.key_comp() == C(5));
333 assert(m.size() == 3);
334 assert(std::distance(m.begin(), m.end()) == 3);
335 assert(*m.begin() == V(1, 1));
336 assert(*std::next(m.begin()) == V(2, 1));
337 assert(*std::next(m.begin(), 2) == V(3, 1));
338
339 assert(mo.key_comp() == C(5));
340 assert(mo.size() == 3);
341 assert(std::distance(mo.begin(), mo.end()) == 3);
342 assert(*mo.begin() == V(1, 1));
343 assert(*std::next(mo.begin()) == V(2, 1));
344 assert(*std::next(mo.begin(), 2) == V(3, 1));
345 }
346 assert(balanced_allocs());
347 #endif
348
349 return 0;
350 }
351