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

source code of libcxx/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp