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