1 | /* Boost.MultiIndex test for copying and assignment. |
2 | * |
3 | * Copyright 2003-2018 Joaquin M Lopez Munoz. |
4 | * Distributed under the Boost Software License, Version 1.0. |
5 | * (See accompanying file LICENSE_1_0.txt or copy at |
6 | * http://www.boost.org/LICENSE_1_0.txt) |
7 | * |
8 | * See http://www.boost.org/libs/multi_index for library home page. |
9 | */ |
10 | |
11 | #include "test_copy_assignment.hpp" |
12 | |
13 | #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */ |
14 | #include <algorithm> |
15 | #include <boost/move/utility_core.hpp> |
16 | #include <list> |
17 | #include <numeric> |
18 | #include <vector> |
19 | #include "pre_multi_index.hpp" |
20 | #include "employee.hpp" |
21 | #include "small_allocator.hpp" |
22 | #include <boost/detail/lightweight_test.hpp> |
23 | |
24 | using namespace boost::multi_index; |
25 | |
26 | #if BOOST_WORKAROUND(__MWERKS__,<=0x3003) |
27 | /* The "ISO C++ Template Parser" option makes CW8.3 incorrectly fail at |
28 | * expressions of the form sizeof(x) where x is an array local to a |
29 | * template function. |
30 | */ |
31 | |
32 | #pragma parse_func_templ off |
33 | #endif |
34 | |
35 | typedef multi_index_container<int> copyable_and_movable; |
36 | |
37 | struct holder |
38 | { |
39 | copyable_and_movable c; |
40 | }; |
41 | |
42 | template<typename Sequence> |
43 | static void test_assign() |
44 | { |
45 | Sequence s; |
46 | |
47 | int a[]={0,1,2,3,4,5}; |
48 | std::size_t sa=sizeof(a)/sizeof(a[0]); |
49 | |
50 | s.assign(&a[0],&a[sa]); |
51 | BOOST_TEST(s.size()==sa&&std::equal(s.begin(),s.end(),&a[0])); |
52 | |
53 | s.assign((const int*)(&a[0]),(const int*)(&a[sa])); |
54 | BOOST_TEST(s.size()==sa&&std::equal(s.begin(),s.end(),&a[0])); |
55 | |
56 | #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) |
57 | s.assign({0,1,2,3,4,5}); |
58 | #else |
59 | s.assign(&a[0],&a[sa]); |
60 | #endif |
61 | |
62 | BOOST_TEST(s.size()==sa&&std::equal(s.begin(),s.end(),&a[0])); |
63 | |
64 | s.assign((std::size_t)18,37); |
65 | BOOST_TEST(s.size()==18&&std::accumulate(s.begin(),s.end(),0)==666); |
66 | |
67 | s.assign((std::size_t)12,167); |
68 | BOOST_TEST(s.size()==12&&std::accumulate(s.begin(),s.end(),0)==2004); |
69 | } |
70 | |
71 | #if BOOST_WORKAROUND(__MWERKS__,<=0x3003) |
72 | #pragma parse_func_templ reset |
73 | #endif |
74 | |
75 | template<typename Sequence> |
76 | static void test_integral_assign() |
77 | { |
78 | /* Special cases described in 23.1.1/9: integral types must not |
79 | * be taken as iterators in assign(f,l) and insert(p,f,l). |
80 | */ |
81 | |
82 | Sequence s; |
83 | |
84 | s.assign(5,10); |
85 | BOOST_TEST(s.size()==5&&std::accumulate(s.begin(),s.end(),0)==50); |
86 | s.assign(2u,5u); |
87 | BOOST_TEST(s.size()==2&&std::accumulate(s.begin(),s.end(),0)==10); |
88 | |
89 | s.clear(); |
90 | s.insert(s.begin(),5,10); |
91 | BOOST_TEST(s.size()==5&&std::accumulate(s.begin(),s.end(),0)==50); |
92 | s.insert(s.begin(),2u,5u); |
93 | BOOST_TEST(s.size()==7&&std::accumulate(s.begin(),s.end(),0)==60); |
94 | } |
95 | |
96 | employee_set produce_employee_set() |
97 | { |
98 | employee_set es; |
99 | es.insert(x: employee(0,"Petr" ,60,2837)); |
100 | es.insert(x: employee(1,"Jiri" ,25,2143)); |
101 | es.insert(x: employee(2,"Radka" ,40,4875)); |
102 | es.insert(x: employee(3,"Milan" ,38,3474)); |
103 | return es; |
104 | } |
105 | |
106 | void test_copy_assignment() |
107 | { |
108 | employee_set es; |
109 | employee_set es2(es); |
110 | |
111 | employee_set::allocator_type al=es.get_allocator(); |
112 | al=get<1>(m&: es).get_allocator(); |
113 | al=get<2>(m&: es).get_allocator(); |
114 | al=get<3>(m&: es).get_allocator(); |
115 | al=get<4>(m&: es).get_allocator(); |
116 | al=get<5>(m&: es).get_allocator(); |
117 | |
118 | BOOST_TEST(es2.empty()); |
119 | |
120 | es2.insert(x: employee(0,"Joe" ,31,1123)); |
121 | es2.insert(x: employee(1,"Robert" ,27,5601)); |
122 | es2.insert(x: employee(2,"John" ,40,7889)); |
123 | es2.insert(x: employee(2,"Aristotle" ,2388,3357)); /* clash */ |
124 | es2.insert(x: employee(3,"Albert" ,20,9012)); |
125 | es2.insert(x: employee(4,"John" ,57,1002)); |
126 | es2.insert(x: employee(0,"Andrew" ,60,2302)); /* clash */ |
127 | |
128 | employee_set es3(es2); |
129 | |
130 | BOOST_TEST(es2==es3); |
131 | BOOST_TEST(get<2>(es2)==get<2>(es3)); |
132 | BOOST_TEST(get<3>(es2)==get<3>(es3)); |
133 | BOOST_TEST(get<5>(es2)==get<5>(es3)); |
134 | |
135 | employee_set es4=employee_set(non_std_allocator<employee>()); |
136 | employee_set_by_name& i1=get<name>(m&: es4); |
137 | i1=get<1>(m&: es2); |
138 | |
139 | BOOST_TEST(es4==es2); |
140 | |
141 | employee_set es5=employee_set(employee_set::ctor_args_list()); |
142 | employee_set_by_age& i2=get<age>(m&: es5); |
143 | i2=get<2>(m&: es2); |
144 | |
145 | BOOST_TEST(i2==get<2>(es2)); |
146 | |
147 | employee_set es6; |
148 | employee_set_as_inserted& i3=get<as_inserted>(m&: es6); |
149 | i3=get<3>(m&: es2); |
150 | |
151 | BOOST_TEST(i3==get<3>(es2)); |
152 | |
153 | employee_set es7; |
154 | employee_set_randomly& i5=get<randomly>(m&: es7); |
155 | i5=get<5>(m&: es2); |
156 | |
157 | BOOST_TEST(i5==get<5>(es2)); |
158 | |
159 | #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)&&\ |
160 | !BOOST_WORKAROUND(BOOST_MSVC,==1800) /* MSVC 12.0 chokes on what follows */ |
161 | employee_set es8({{0,"Rose" ,40,4512},{1,"Mary" ,38,3345},{2,"Jo" ,25,7102}}); |
162 | employee_set es9; |
163 | es9={{0,"Rose" ,40,4512},{1,"Mary" ,38,3345},{2,"Jo" ,25,7102}, |
164 | {0,"Rose" ,40,4512}}; |
165 | |
166 | BOOST_TEST(es8.size()==3); |
167 | BOOST_TEST(es9==es8); |
168 | |
169 | es9.clear(); |
170 | get<0>(m&: es9)={{0,"Rose" ,40,4512},{1,"Mary" ,38,3345},{2,"Jo" ,25,7102}, |
171 | {0,"Rose" ,40,4512}}; |
172 | BOOST_TEST(es9==es8); |
173 | |
174 | es9.clear(); |
175 | get<0>(m&: es9)={{0,"Rose" ,40,4512},{2,"Jo" ,25,7102},{1,"Mary" ,38,3345}}; |
176 | BOOST_TEST(es9==es8); |
177 | |
178 | es9.clear(); |
179 | get<1>(m&: es9)={{1,"Mary" ,38,3345},{0,"Rose" ,40,4512},{2,"Jo" ,25,7102}, |
180 | {0,"Rose" ,40,4512}}; |
181 | BOOST_TEST(es9==es8); |
182 | |
183 | es9.clear(); |
184 | get<2>(m&: es9)={{2,"Jo" ,25,7102},{0,"Rose" ,40,4512},{1,"Mary" ,38,3345}}; |
185 | BOOST_TEST(es9==es8); |
186 | |
187 | es9.clear(); |
188 | get<3>(m&: es9)={{0,"Rose" ,40,4512},{1,"Mary" ,38,3345},{1,"Mary" ,38,3345}, |
189 | {2,"Jo" ,25,7102}}; |
190 | BOOST_TEST(es9==es8); |
191 | |
192 | es9.clear(); |
193 | get<4>(m&: es9)={{1,"Mary" ,38,3345},{2,"Jo" ,25,7102},{0,"Rose" ,40,4512}}; |
194 | BOOST_TEST(es9==es8); |
195 | |
196 | es9.clear(); |
197 | get<5>(m&: es9)={{1,"Mary" ,38,3345},{2,"Jo" ,25,7102},{0,"Rose" ,40,4512}, |
198 | {2,"Jo" ,25,7102}}; |
199 | BOOST_TEST(es9==es8); |
200 | #endif |
201 | |
202 | employee_set es10(produce_employee_set()),es11(produce_employee_set()); |
203 | BOOST_TEST(es10==es11); |
204 | |
205 | employee_set es12(boost::move(t&: es10)); |
206 | BOOST_TEST(es10.empty()); |
207 | BOOST_TEST(es11==es12); |
208 | |
209 | es10=boost::move(t&: es12); |
210 | BOOST_TEST(es12.empty()); |
211 | BOOST_TEST(es11==es10); |
212 | |
213 | std::list<employee> l; |
214 | l.push_back(x: employee(3,"Anna" ,31,5388)); |
215 | l.push_back(x: employee(1,"Rachel" ,27,9012)); |
216 | l.push_back(x: employee(2,"Agatha" ,40,1520)); |
217 | |
218 | employee_set es13(l.begin(),l.end()); |
219 | |
220 | l.sort(); |
221 | |
222 | BOOST_TEST(es13.size()==l.size()&& |
223 | std::equal(es13.begin(),es13.end(),l.begin())); |
224 | |
225 | test_assign<multi_index_container<int,indexed_by<sequenced<> > > >(); |
226 | test_integral_assign< |
227 | multi_index_container<int,indexed_by<sequenced<> > > >(); |
228 | |
229 | test_assign<multi_index_container<int,indexed_by<random_access<> > > >(); |
230 | test_integral_assign< |
231 | multi_index_container<int,indexed_by<random_access<> > > >(); |
232 | |
233 | /* Testcase for problem described at http://www.boost.org/doc/html/move/ |
234 | * emulation_limitations.html#move.emulation_limitations.assignment_operator |
235 | */ |
236 | |
237 | holder h((holder())); |
238 | h=holder(); |
239 | |
240 | #if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) |
241 | { |
242 | /* testcase for https://svn.boost.org/trac10/ticket/13518 */ |
243 | |
244 | multi_index_container<int> x={}; |
245 | } |
246 | #endif |
247 | |
248 | typedef small_allocator<int> small_alloc; |
249 | typedef multi_index_container< |
250 | int, |
251 | indexed_by< |
252 | ordered_unique<identity<int> >, |
253 | ranked_unique<identity<int> >, |
254 | hashed_unique<identity<int> >, |
255 | sequenced<>, |
256 | random_access<> |
257 | >, |
258 | small_alloc |
259 | > small_container; |
260 | typedef small_container::nth_index<0>::type small_container_0; |
261 | typedef small_container::nth_index<1>::type small_container_1; |
262 | typedef small_container::nth_index<2>::type small_container_2; |
263 | typedef small_container::nth_index<3>::type small_container_3; |
264 | typedef small_container::nth_index<4>::type small_container_4; |
265 | |
266 | BOOST_STATIC_ASSERT(( |
267 | boost::is_same<small_container::size_type,small_alloc::size_type>::value)); |
268 | BOOST_STATIC_ASSERT(( |
269 | boost::is_same< |
270 | small_container::difference_type,small_alloc::difference_type>::value)); |
271 | BOOST_STATIC_ASSERT(( |
272 | boost::is_same<small_container_0::size_type,small_alloc::size_type>::value)); |
273 | BOOST_STATIC_ASSERT(( |
274 | boost::is_same< |
275 | small_container_0::difference_type,small_alloc::difference_type>::value)); |
276 | BOOST_STATIC_ASSERT(( |
277 | boost::is_same<small_container_1::size_type,small_alloc::size_type>::value)); |
278 | BOOST_STATIC_ASSERT(( |
279 | boost::is_same< |
280 | small_container_1::difference_type,small_alloc::difference_type>::value)); |
281 | BOOST_STATIC_ASSERT(( |
282 | boost::is_same<small_container_2::size_type,small_alloc::size_type>::value)); |
283 | BOOST_STATIC_ASSERT(( |
284 | boost::is_same< |
285 | small_container_2::difference_type,small_alloc::difference_type>::value)); |
286 | BOOST_STATIC_ASSERT(( |
287 | boost::is_same<small_container_3::size_type,small_alloc::size_type>::value)); |
288 | BOOST_STATIC_ASSERT(( |
289 | boost::is_same< |
290 | small_container_3::difference_type,small_alloc::difference_type>::value)); |
291 | BOOST_STATIC_ASSERT(( |
292 | boost::is_same<small_container_4::size_type,small_alloc::size_type>::value)); |
293 | BOOST_STATIC_ASSERT(( |
294 | boost::is_same< |
295 | small_container_4::difference_type,small_alloc::difference_type>::value)); |
296 | |
297 | small_container sc; |
298 | small_container_0& sc0=sc.get<0>(); |
299 | small_container_1& sc1=sc.get<1>(); |
300 | small_container_2& sc2=sc.get<2>(); |
301 | small_container_3& sc3=sc.get<3>(); |
302 | small_container_4& sc4=sc.get<4>(); |
303 | small_alloc::size_type s, |
304 | ms=(small_alloc::size_type)(-1); |
305 | |
306 | sc.insert(x: 0); |
307 | |
308 | s=sc0.size(); |
309 | BOOST_TEST(sc0.max_size()<=ms); |
310 | s=sc0.erase(x: 1); |
311 | s=sc0.count(x: 0); |
312 | s=sc0.count(x: 0,comp: std::less<int>()); |
313 | |
314 | s=sc1.size(); |
315 | BOOST_TEST(sc1.max_size()<=ms); |
316 | s=sc1.erase(x: 1); |
317 | s=sc1.count(x: 0); |
318 | s=sc1.count(x: 0,comp: std::less<int>()); |
319 | (void)sc1.nth(n: s); |
320 | s=sc1.rank(position: sc1.begin()); |
321 | s=sc1.find_rank(x: 0); |
322 | s=sc1.find_rank(x: 0,comp: std::less<int>()); |
323 | s=sc1.lower_bound_rank(x: 0); |
324 | s=sc1.lower_bound_rank(x: 0,comp: std::less<int>()); |
325 | s=sc1.upper_bound_rank(x: 0); |
326 | s=sc1.upper_bound_rank(x: 0,comp: std::less<int>()); |
327 | s=sc1.equal_range_rank(x: 0).first; |
328 | s=sc1.equal_range_rank(x: 0).second; |
329 | s=sc1.range_rank(lower: unbounded,upper: unbounded).first; |
330 | s=sc1.range_rank(lower: unbounded,upper: unbounded).second; |
331 | |
332 | s=sc2.size(); |
333 | BOOST_TEST(sc2.max_size()<=ms); |
334 | s=sc2.erase(k: 1); |
335 | s=sc2.count(k: 0); |
336 | s=sc2.count(k: 0,hash: boost::hash<int>(),eq: std::equal_to<int>()); |
337 | s=sc2.bucket_count(); |
338 | BOOST_TEST(sc2.max_bucket_count()<=ms); |
339 | BOOST_TEST(sc2.bucket_size((small_alloc::size_type)(0))<=ms); |
340 | BOOST_TEST(sc2.bucket_size(0)<=ms); |
341 | (void)sc2.begin(n: 0); |
342 | (void)sc2.end(n: 0); |
343 | (void)sc2.cbegin(n: 0); |
344 | (void)sc2.cend(n: 0); |
345 | sc2.rehash(n: 2); |
346 | sc2.reserve(n: 2); |
347 | |
348 | s=sc3.size(); |
349 | BOOST_TEST(sc3.max_size()<=ms); |
350 | sc3.resize(n: 0); |
351 | sc3.resize(n: 0,x: 0); |
352 | sc3.assign(n: (small_alloc::size_type)(1),value: 0); |
353 | sc3.insert(position: sc3.begin(),n: (small_alloc::size_type)(0),x: 0); |
354 | |
355 | s=sc4.size(); |
356 | BOOST_TEST(sc4.max_size()<=ms); |
357 | BOOST_TEST(sc4.capacity()<=ms); |
358 | sc4.reserve(n: 0); |
359 | sc4.resize(n: 0); |
360 | sc4.resize(n: 0,x: 0); |
361 | sc4.assign(n: (small_alloc::size_type)(1),value: 0); |
362 | (void)sc4[0]; |
363 | (void)sc4.at(n: 0); |
364 | sc4.insert(position: sc4.begin(),n: (small_alloc::size_type)(0),x: 0); |
365 | } |
366 | |