1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // (C) Copyright Ion Gaztanaga 2004-2013. Distributed under the Boost |
4 | // Software License, Version 1.0. (See accompanying file |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | // |
7 | // See http://www.boost.org/libs/container for documentation. |
8 | // |
9 | ////////////////////////////////////////////////////////////////////////////// |
10 | |
11 | #include <iostream> |
12 | #include <set> |
13 | #include <utility> |
14 | #include <vector> |
15 | |
16 | #include <boost/container/flat_set.hpp> |
17 | #include <boost/container/detail/container_or_allocator_rebind.hpp> |
18 | |
19 | #include "print_container.hpp" |
20 | #include "dummy_test_allocator.hpp" |
21 | #include "movable_int.hpp" |
22 | #include "set_test.hpp" |
23 | #include "propagate_allocator_test.hpp" |
24 | #include "emplace_test.hpp" |
25 | #include "container_common_tests.hpp" |
26 | #include "../../intrusive/test/iterator_test.hpp" |
27 | |
28 | using namespace boost::container; |
29 | |
30 | //Test recursive structures |
31 | class recursive_flat_set |
32 | { |
33 | public: |
34 | recursive_flat_set(const recursive_flat_set &c) |
35 | : id_(c.id_), flat_set_(c.flat_set_) |
36 | {} |
37 | |
38 | recursive_flat_set & operator =(const recursive_flat_set &c) |
39 | { |
40 | id_ = c.id_; |
41 | flat_set_= c.flat_set_; |
42 | return *this; |
43 | } |
44 | int id_; |
45 | flat_set<recursive_flat_set> flat_set_; |
46 | flat_set<recursive_flat_set>::iterator it_; |
47 | flat_set<recursive_flat_set>::const_iterator cit_; |
48 | flat_set<recursive_flat_set>::reverse_iterator rit_; |
49 | flat_set<recursive_flat_set>::const_reverse_iterator crit_; |
50 | |
51 | friend bool operator< (const recursive_flat_set &a, const recursive_flat_set &b) |
52 | { return a.id_ < b.id_; } |
53 | }; |
54 | |
55 | |
56 | //Test recursive structures |
57 | class recursive_flat_multiset |
58 | { |
59 | public: |
60 | recursive_flat_multiset(const recursive_flat_multiset &c) |
61 | : id_(c.id_), flat_multiset_(c.flat_multiset_) |
62 | {} |
63 | |
64 | recursive_flat_multiset & operator =(const recursive_flat_multiset &c) |
65 | { |
66 | id_ = c.id_; |
67 | flat_multiset_= c.flat_multiset_; |
68 | return *this; |
69 | } |
70 | int id_; |
71 | flat_multiset<recursive_flat_multiset> flat_multiset_; |
72 | flat_multiset<recursive_flat_multiset>::iterator it_; |
73 | flat_multiset<recursive_flat_multiset>::const_iterator cit_; |
74 | flat_multiset<recursive_flat_multiset>::reverse_iterator rit_; |
75 | flat_multiset<recursive_flat_multiset>::const_reverse_iterator crit_; |
76 | |
77 | friend bool operator< (const recursive_flat_multiset &a, const recursive_flat_multiset &b) |
78 | { return a.id_ < b.id_; } |
79 | }; |
80 | |
81 | |
82 | template<class C> |
83 | void test_move() |
84 | { |
85 | //Now test move semantics |
86 | C original; |
87 | C move_ctor(boost::move(original)); |
88 | C move_assign; |
89 | move_assign = boost::move(move_ctor); |
90 | move_assign.swap(original); |
91 | } |
92 | |
93 | namespace boost{ |
94 | namespace container { |
95 | namespace test{ |
96 | |
97 | bool flat_tree_ordered_insertion_test() |
98 | { |
99 | using namespace boost::container; |
100 | const std::size_t NumElements = 100; |
101 | |
102 | //Ordered insertion multiset |
103 | { |
104 | std::multiset<int> int_mset; |
105 | for(std::size_t i = 0; i != NumElements; ++i){ |
106 | int_mset.insert(x: static_cast<int>(i)); |
107 | } |
108 | //Construction insertion |
109 | flat_multiset<int> fmset(ordered_range, int_mset.begin(), int_mset.end()); |
110 | if(!CheckEqualContainers(cont_a: int_mset, cont_b: fmset)) |
111 | return false; |
112 | //Insertion when empty |
113 | fmset.clear(); |
114 | fmset.insert(ordered_range, first: int_mset.begin(), last: int_mset.end()); |
115 | if(!CheckEqualContainers(cont_a: int_mset, cont_b: fmset)) |
116 | return false; |
117 | //Re-insertion |
118 | fmset.insert(ordered_range, first: int_mset.begin(), last: int_mset.end()); |
119 | std::multiset<int> int_mset2(int_mset); |
120 | int_mset2.insert(first: int_mset.begin(), last: int_mset.end()); |
121 | if(!CheckEqualContainers(cont_a: int_mset2, cont_b: fmset)) |
122 | return false; |
123 | //Re-re-insertion |
124 | fmset.insert(ordered_range, first: int_mset2.begin(), last: int_mset2.end()); |
125 | std::multiset<int> int_mset4(int_mset2); |
126 | int_mset4.insert(first: int_mset2.begin(), last: int_mset2.end()); |
127 | if(!CheckEqualContainers(cont_a: int_mset4, cont_b: fmset)) |
128 | return false; |
129 | //Re-re-insertion of even |
130 | std::multiset<int> int_even_mset; |
131 | for(std::size_t i = 0; i < NumElements; i+=2){ |
132 | int_mset.insert(x: static_cast<int>(i)); |
133 | } |
134 | fmset.insert(ordered_range, first: int_even_mset.begin(), last: int_even_mset.end()); |
135 | int_mset4.insert(first: int_even_mset.begin(), last: int_even_mset.end()); |
136 | if(!CheckEqualContainers(cont_a: int_mset4, cont_b: fmset)) |
137 | return false; |
138 | |
139 | //Re-re-insertion using in-place merge |
140 | fmset.reserve(cnt: fmset.size() + int_mset2.size()); |
141 | fmset.insert(ordered_range, first: int_mset2.begin(), last: int_mset2.end()); |
142 | std::multiset<int> int_mset5(int_mset2); |
143 | int_mset4.insert(first: int_mset5.begin(), last: int_mset5.end()); |
144 | if(!CheckEqualContainers(cont_a: int_mset4, cont_b: fmset)) |
145 | return false; |
146 | //Re-re-insertion of even |
147 | std::multiset<int> int_even_mset2; |
148 | for(std::size_t i = 0; i < NumElements; i+=2){ |
149 | int_even_mset2.insert(x: static_cast<int>(i)); |
150 | } |
151 | fmset.reserve(cnt: fmset.size() + int_even_mset2.size()); |
152 | fmset.insert(ordered_range, first: int_even_mset2.begin(), last: int_even_mset2.end()); |
153 | int_mset4.insert(first: int_even_mset2.begin(), last: int_even_mset2.end()); |
154 | if(!CheckEqualContainers(cont_a: int_mset4, cont_b: fmset)) |
155 | return false; |
156 | } |
157 | |
158 | //Ordered insertion set |
159 | { |
160 | std::set<int> int_set; |
161 | for(std::size_t i = 0; i != NumElements; ++i){ |
162 | int_set.insert(x: static_cast<int>(i)); |
163 | } |
164 | //Construction insertion |
165 | flat_set<int> fset(ordered_unique_range, int_set.begin(), int_set.end()); |
166 | if(!CheckEqualContainers(cont_a: int_set, cont_b: fset)) |
167 | return false; |
168 | //Insertion when empty |
169 | fset.clear(); |
170 | fset.insert(ordered_unique_range, first: int_set.begin(), last: int_set.end()); |
171 | if(!CheckEqualContainers(cont_a: int_set, cont_b: fset)) |
172 | return false; |
173 | //Re-insertion |
174 | fset.insert(ordered_unique_range, first: int_set.begin(), last: int_set.end()); |
175 | std::set<int> int_set2(int_set); |
176 | int_set2.insert(first: int_set.begin(), last: int_set.end()); |
177 | if(!CheckEqualContainers(cont_a: int_set2, cont_b: fset)) |
178 | return false; |
179 | //Re-re-insertion |
180 | fset.insert(ordered_unique_range, first: int_set2.begin(), last: int_set2.end()); |
181 | std::set<int> int_set4(int_set2); |
182 | int_set4.insert(first: int_set2.begin(), last: int_set2.end()); |
183 | if(!CheckEqualContainers(cont_a: int_set4, cont_b: fset)) |
184 | return false; |
185 | //Re-re-insertion of even |
186 | std::set<int> int_even_set; |
187 | for(std::size_t i = 0; i < NumElements; i+=2){ |
188 | int_even_set.insert(x: static_cast<int>(i)); |
189 | } |
190 | fset.insert(ordered_unique_range, first: int_even_set.begin(), last: int_even_set.end()); |
191 | int_set4.insert(first: int_even_set.begin(), last: int_even_set.end()); |
192 | if(!CheckEqualContainers(cont_a: int_set4, cont_b: fset)) |
193 | return false; |
194 | //Partial Re-re-insertion of even |
195 | int_even_set.clear(); |
196 | for(std::size_t i = 0; i < NumElements; i+=4){ |
197 | int_even_set.insert(x: static_cast<int>(i)); |
198 | } |
199 | fset.clear(); |
200 | int_set4.clear(); |
201 | //insert 0,4,8,12... |
202 | fset.insert(ordered_unique_range, first: int_even_set.begin(), last: int_even_set.end()); |
203 | int_set4.insert(first: int_even_set.begin(), last: int_even_set.end()); |
204 | if(!CheckEqualContainers(cont_a: int_set4, cont_b: fset)) |
205 | return false; |
206 | for(std::size_t i = 2; i < NumElements; i+=4){ |
207 | int_even_set.insert(x: static_cast<int>(i)); |
208 | } |
209 | //insert 0,2,4,6,8,10,12... |
210 | fset.insert(ordered_unique_range, first: int_even_set.begin(), last: int_even_set.end()); |
211 | int_set4.insert(first: int_even_set.begin(), last: int_even_set.end()); |
212 | if(!CheckEqualContainers(cont_a: int_set4, cont_b: fset)) |
213 | return false; |
214 | int_even_set.clear(); |
215 | for(std::size_t i = 0; i < NumElements; i+=8){ |
216 | int_even_set.insert(x: static_cast<int>(i)); |
217 | } |
218 | fset.clear(); |
219 | int_set4.clear(); |
220 | //insert 0,8,16... |
221 | fset.insert(ordered_unique_range, first: int_even_set.begin(), last: int_even_set.end()); |
222 | int_set4.insert(first: int_even_set.begin(), last: int_even_set.end()); |
223 | if(!CheckEqualContainers(cont_a: int_set4, cont_b: fset)) |
224 | return false; |
225 | for(std::size_t i = 0; i < NumElements; i+=2){ |
226 | int_even_set.insert(x: static_cast<int>(i)); |
227 | } |
228 | //insert 0,2,4,6,8,10,12... |
229 | fset.insert(ordered_unique_range, first: int_even_set.begin(), last: int_even_set.end()); |
230 | int_set4.insert(first: int_even_set.begin(), last: int_even_set.end()); |
231 | if(!CheckEqualContainers(cont_a: int_set4, cont_b: fset)) |
232 | return false; |
233 | |
234 | |
235 | int_even_set.clear(); |
236 | for(std::size_t i = 0; i < NumElements; i+=8){ |
237 | int_even_set.insert(x: static_cast<int>(i)); |
238 | int_even_set.insert(x: static_cast<int>(i+2)); |
239 | } |
240 | int_even_set.insert(x: static_cast<int>(NumElements-2)); |
241 | fset.clear(); |
242 | int_set4.clear(); |
243 | //insert 0,2,8,10... |
244 | fset.insert(ordered_unique_range, first: int_even_set.begin(), last: int_even_set.end()); |
245 | int_set4.insert(first: int_even_set.begin(), last: int_even_set.end()); |
246 | if(!CheckEqualContainers(cont_a: int_set4, cont_b: fset)) |
247 | return false; |
248 | for(std::size_t i = 0; i < NumElements; i+=2){ |
249 | int_even_set.insert(x: static_cast<int>(i)); |
250 | } |
251 | //insert 0,2,4,6,8,10,12... |
252 | fset.insert(ordered_unique_range, first: int_even_set.begin(), last: int_even_set.end()); |
253 | int_set4.insert(first: int_even_set.begin(), last: int_even_set.end()); |
254 | if(!CheckEqualContainers(cont_a: int_set4, cont_b: fset)) |
255 | return false; |
256 | |
257 | //add even/odd values with not enough capacity |
258 | flat_set<int>().swap(other&: fset); |
259 | int_set4.clear(); |
260 | int_set.clear(); |
261 | |
262 | fset.reserve(cnt: int_even_set.size()); |
263 | fset.insert(ordered_unique_range, first: int_even_set.begin(), last: int_even_set.end()); |
264 | int_set4.insert(first: int_even_set.begin(), last: int_even_set.end()); |
265 | |
266 | for(std::size_t i = 0; i < NumElements*2; i+=2){ |
267 | int_set.insert(x: static_cast<int>(i)); |
268 | int_set.insert(x: static_cast<int>(i+1)); |
269 | } |
270 | |
271 | fset.insert(ordered_unique_range, first: int_set.begin(), last: int_set.end()); |
272 | int_set4.insert(first: int_set.begin(), last: int_set.end()); |
273 | if(!CheckEqualContainers(cont_a: int_set4, cont_b: fset)) |
274 | return false; |
275 | } |
276 | |
277 | return true; |
278 | } |
279 | |
280 | bool constructor_template_auto_deduction_test() |
281 | { |
282 | |
283 | #ifndef BOOST_CONTAINER_NO_CXX17_CTAD |
284 | using namespace boost::container; |
285 | const std::size_t NumElements = 100; |
286 | { |
287 | std::set<int> int_set; |
288 | for (std::size_t i = 0; i != NumElements; ++i) { |
289 | int_set.insert(x: static_cast<int>(i)); |
290 | } |
291 | std::multiset<int> int_mset; |
292 | for (std::size_t i = 0; i != NumElements; ++i) { |
293 | int_mset.insert(x: static_cast<int>(i)); |
294 | } |
295 | |
296 | typedef std::less<int> comp_int_t; |
297 | typedef std::allocator<int> alloc_int_t; |
298 | |
299 | //range |
300 | { |
301 | auto fset = flat_set(int_set.begin(), int_set.end()); |
302 | if (!CheckEqualContainers(cont_a: int_set, cont_b: fset)) |
303 | return false; |
304 | auto fmset = flat_multiset(int_mset.begin(), int_mset.end()); |
305 | if (!CheckEqualContainers(cont_a: int_mset, cont_b: fmset)) |
306 | return false; |
307 | } |
308 | //range+comp |
309 | { |
310 | auto fset = flat_set(int_set.begin(), int_set.end(), comp_int_t()); |
311 | if (!CheckEqualContainers(cont_a: int_set, cont_b: fset)) |
312 | return false; |
313 | auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), comp_int_t()); |
314 | if (!CheckEqualContainers(cont_a: int_mset, cont_b: fmset)) |
315 | return false; |
316 | } |
317 | //range+comp+alloc |
318 | { |
319 | auto fset = flat_set(int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t()); |
320 | if (!CheckEqualContainers(cont_a: int_set, cont_b: fset)) |
321 | return false; |
322 | auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t()); |
323 | if (!CheckEqualContainers(cont_a: int_mset, cont_b: fmset)) |
324 | return false; |
325 | } |
326 | //range+alloc |
327 | { |
328 | auto fset = flat_set(int_set.begin(), int_set.end(), alloc_int_t()); |
329 | if (!CheckEqualContainers(cont_a: int_set, cont_b: fset)) |
330 | return false; |
331 | auto fmset = flat_multiset(int_mset.begin(), int_mset.end(), alloc_int_t()); |
332 | if (!CheckEqualContainers(cont_a: int_mset, cont_b: fmset)) |
333 | return false; |
334 | } |
335 | |
336 | //ordered_unique_range / ordered_range |
337 | |
338 | //range |
339 | { |
340 | auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end()); |
341 | if (!CheckEqualContainers(cont_a: int_set, cont_b: fset)) |
342 | return false; |
343 | auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end()); |
344 | if (!CheckEqualContainers(cont_a: int_mset, cont_b: fmset)) |
345 | return false; |
346 | } |
347 | //range+comp |
348 | { |
349 | auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t()); |
350 | if (!CheckEqualContainers(cont_a: int_set, cont_b: fset)) |
351 | return false; |
352 | auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t()); |
353 | if (!CheckEqualContainers(cont_a: int_mset, cont_b: fmset)) |
354 | return false; |
355 | } |
356 | //range+comp+alloc |
357 | { |
358 | auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), comp_int_t(), alloc_int_t()); |
359 | if (!CheckEqualContainers(cont_a: int_set, cont_b: fset)) |
360 | return false; |
361 | auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), comp_int_t(), alloc_int_t()); |
362 | if (!CheckEqualContainers(cont_a: int_mset, cont_b: fmset)) |
363 | return false; |
364 | } |
365 | //range+alloc |
366 | { |
367 | auto fset = flat_set(ordered_unique_range, int_set.begin(), int_set.end(), alloc_int_t()); |
368 | if (!CheckEqualContainers(cont_a: int_set, cont_b: fset)) |
369 | return false; |
370 | auto fmset = flat_multiset(ordered_range, int_mset.begin(), int_mset.end(), alloc_int_t()); |
371 | if (!CheckEqualContainers(cont_a: int_mset, cont_b: fmset)) |
372 | return false; |
373 | } |
374 | } |
375 | #endif |
376 | |
377 | return true; |
378 | } |
379 | |
380 | template< class RandomIt > |
381 | void random_shuffle( RandomIt first, RandomIt last ) |
382 | { |
383 | typedef typename boost::container::iterator_traits<RandomIt>::difference_type difference_type; |
384 | difference_type n = last - first; |
385 | for (difference_type i = n-1; i > 0; --i) { |
386 | difference_type j = std::rand() % (i+1); |
387 | if(j != i) { |
388 | boost::adl_move_swap(first[i], first[j]); |
389 | } |
390 | } |
391 | } |
392 | |
393 | bool () |
394 | { |
395 | using namespace boost::container; |
396 | const std::size_t NumElements = 100; |
397 | |
398 | //extract/adopt set |
399 | { |
400 | //Construction insertion |
401 | flat_set<int> fset; |
402 | |
403 | for(std::size_t i = 0; i != NumElements; ++i){ |
404 | fset.insert(x: static_cast<int>(i)); |
405 | } |
406 | |
407 | const flat_set<int> fset_copy(fset); |
408 | flat_set<int>::sequence_type seq(fset.extract_sequence()); |
409 | if(!fset.empty()) |
410 | return false; |
411 | if(!CheckEqualContainers(cont_a: seq, cont_b: fset_copy)) |
412 | return false; |
413 | |
414 | seq.insert(pos: seq.end(), first: fset_copy.begin(), last: fset_copy.end()); |
415 | boost::container::test::random_shuffle(first: seq.begin(), last: seq.end()); |
416 | fset.adopt_sequence(seq: boost::move(t&: seq)); |
417 | if(!CheckEqualContainers(cont_a: fset, cont_b: fset_copy)) |
418 | return false; |
419 | if (!CheckEqualContainers(cont_a: fset.sequence(), cont_b: fset_copy.sequence())) |
420 | return false; |
421 | } |
422 | |
423 | //extract/adopt set, ordered_unique_range |
424 | { |
425 | //Construction insertion |
426 | flat_set<int> fset; |
427 | |
428 | for(std::size_t i = 0; i != NumElements; ++i){ |
429 | fset.insert(x: static_cast<int>(i)); |
430 | } |
431 | |
432 | const flat_set<int> fset_copy(fset); |
433 | flat_set<int>::sequence_type seq(fset.extract_sequence()); |
434 | if(!fset.empty()) |
435 | return false; |
436 | if(!CheckEqualContainers(cont_a: seq, cont_b: fset_copy)) |
437 | return false; |
438 | |
439 | fset.adopt_sequence(ordered_unique_range, seq: boost::move(t&: seq)); |
440 | if(!CheckEqualContainers(cont_a: fset, cont_b: fset_copy)) |
441 | return false; |
442 | if (!CheckEqualContainers(cont_a: fset.sequence(), cont_b: fset_copy.sequence())) |
443 | return false; |
444 | } |
445 | |
446 | //extract/adopt multiset |
447 | { |
448 | //Construction insertion |
449 | flat_multiset<int> fmset; |
450 | |
451 | for(std::size_t i = 0; i != NumElements; ++i){ |
452 | fmset.insert(x: static_cast<int>(i)); |
453 | fmset.insert(x: static_cast<int>(i)); |
454 | } |
455 | |
456 | const flat_multiset<int> fmset_copy(fmset); |
457 | flat_multiset<int>::sequence_type seq(fmset.extract_sequence()); |
458 | if(!fmset.empty()) |
459 | return false; |
460 | if(!CheckEqualContainers(cont_a: seq, cont_b: fmset_copy)) |
461 | return false; |
462 | |
463 | boost::container::test::random_shuffle(first: seq.begin(), last: seq.end()); |
464 | fmset.adopt_sequence(seq: boost::move(t&: seq)); |
465 | if(!CheckEqualContainers(cont_a: fmset, cont_b: fmset_copy)) |
466 | return false; |
467 | if (!CheckEqualContainers(cont_a: fmset.sequence(), cont_b: fmset_copy.sequence())) |
468 | return false; |
469 | } |
470 | |
471 | //extract/adopt multiset, ordered_range |
472 | { |
473 | //Construction insertion |
474 | flat_multiset<int> fmset; |
475 | |
476 | for(std::size_t i = 0; i != NumElements; ++i){ |
477 | fmset.insert(x: static_cast<int>(i)); |
478 | fmset.insert(x: static_cast<int>(i)); |
479 | } |
480 | |
481 | const flat_multiset<int> fmset_copy(fmset); |
482 | flat_multiset<int>::sequence_type seq(fmset.extract_sequence()); |
483 | if(!fmset.empty()) |
484 | return false; |
485 | if(!CheckEqualContainers(cont_a: seq, cont_b: fmset_copy)) |
486 | return false; |
487 | |
488 | fmset.adopt_sequence(ordered_range, seq: boost::move(t&: seq)); |
489 | if(!CheckEqualContainers(cont_a: fmset, cont_b: fmset_copy)) |
490 | return false; |
491 | if (!CheckEqualContainers(cont_a: fmset.sequence(), cont_b: fmset_copy.sequence())) |
492 | return false; |
493 | } |
494 | |
495 | return true; |
496 | } |
497 | |
498 | bool test_heterogeneous_lookups() |
499 | { |
500 | typedef flat_set<int, test::less_transparent> set_t; |
501 | typedef flat_multiset<int, test::less_transparent> mset_t; |
502 | |
503 | set_t set1; |
504 | mset_t mset1; |
505 | |
506 | const set_t &cset1 = set1; |
507 | const mset_t &cmset1 = mset1; |
508 | |
509 | set1.insert(x: 1); |
510 | set1.insert(x: 1); |
511 | set1.insert(x: 2); |
512 | set1.insert(x: 2); |
513 | set1.insert(x: 3); |
514 | |
515 | mset1.insert(x: 1); |
516 | mset1.insert(x: 1); |
517 | mset1.insert(x: 2); |
518 | mset1.insert(x: 2); |
519 | mset1.insert(x: 3); |
520 | |
521 | const test::non_copymovable_int find_me(2); |
522 | |
523 | //find |
524 | if(*set1.find(k: find_me) != 2) |
525 | return false; |
526 | if(*cset1.find(k: find_me) != 2) |
527 | return false; |
528 | if(*mset1.find(k: find_me) != 2) |
529 | return false; |
530 | if(*cmset1.find(k: find_me) != 2) |
531 | return false; |
532 | |
533 | //count |
534 | if(set1.count(x: find_me) != 1) |
535 | return false; |
536 | if(cset1.count(x: find_me) != 1) |
537 | return false; |
538 | if(mset1.count(k: find_me) != 2) |
539 | return false; |
540 | if(cmset1.count(k: find_me) != 2) |
541 | return false; |
542 | |
543 | //contains |
544 | if(!set1.contains(x: find_me)) |
545 | return false; |
546 | if(!cset1.contains(x: find_me)) |
547 | return false; |
548 | if(!mset1.contains(x: find_me)) |
549 | return false; |
550 | if(!cmset1.contains(x: find_me)) |
551 | return false; |
552 | |
553 | //lower_bound |
554 | if(*set1.lower_bound(k: find_me) != 2) |
555 | return false; |
556 | if(*cset1.lower_bound(k: find_me) != 2) |
557 | return false; |
558 | if(*mset1.lower_bound(k: find_me) != 2) |
559 | return false; |
560 | if(*cmset1.lower_bound(k: find_me) != 2) |
561 | return false; |
562 | |
563 | //upper_bound |
564 | if(*set1.upper_bound(k: find_me) != 3) |
565 | return false; |
566 | if(*cset1.upper_bound(k: find_me) != 3) |
567 | return false; |
568 | if(*mset1.upper_bound(k: find_me) != 3) |
569 | return false; |
570 | if(*cmset1.upper_bound(k: find_me) != 3) |
571 | return false; |
572 | |
573 | //equal_range |
574 | if(*set1.equal_range(x: find_me).first != 2) |
575 | return false; |
576 | if(*cset1.equal_range(x: find_me).second != 3) |
577 | return false; |
578 | if(*mset1.equal_range(k: find_me).first != 2) |
579 | return false; |
580 | if(*cmset1.equal_range(k: find_me).second != 3) |
581 | return false; |
582 | |
583 | return true; |
584 | } |
585 | |
586 | // An ordered sequence of std:pair is also ordered by std::pair::first. |
587 | struct with_lookup_by_first |
588 | { |
589 | typedef void is_transparent; |
590 | inline bool operator()(std::pair<int, int> a, std::pair<int, int> b) const |
591 | { |
592 | return a < b; |
593 | } |
594 | inline bool operator()(std::pair<int, int> a, int first) const |
595 | { |
596 | return a.first < first; |
597 | } |
598 | inline bool operator()(int first, std::pair<int, int> b) const |
599 | { |
600 | return first < b.first; |
601 | } |
602 | }; |
603 | |
604 | bool test_heterogeneous_lookup_by_partial_key() |
605 | { |
606 | typedef flat_set<std::pair<int, int>, with_lookup_by_first> set_t; |
607 | |
608 | set_t set1; |
609 | set1.insert(x: std::pair<int, int>(0, 1)); |
610 | set1.insert(x: std::pair<int, int>(0, 2)); |
611 | |
612 | std::pair<set_t::iterator, set_t::iterator> const first_0_range = set1.equal_range(x: 0); |
613 | if(2 != (first_0_range.second - first_0_range.first)) |
614 | return false; |
615 | |
616 | if(2 != set1.count(x: 0)) |
617 | return false; |
618 | return true; |
619 | } |
620 | |
621 | }}} |
622 | |
623 | template<class VoidAllocatorOrContainer> |
624 | struct GetSetContainer |
625 | { |
626 | template<class ValueType> |
627 | struct apply |
628 | { |
629 | typedef flat_set < ValueType |
630 | , std::less<ValueType> |
631 | , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, ValueType>::type |
632 | > set_type; |
633 | |
634 | typedef flat_multiset < ValueType |
635 | , std::less<ValueType> |
636 | , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, ValueType>::type |
637 | > multiset_type; |
638 | }; |
639 | }; |
640 | |
641 | template<typename FlatSetType> |
642 | bool test_support_for_initialization_list_for() |
643 | { |
644 | #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) |
645 | const std::initializer_list<int> il |
646 | = {1, 2}; |
647 | |
648 | const FlatSetType expected(il.begin(), il.end()); |
649 | { |
650 | const FlatSetType sil = il; |
651 | if (sil != expected) |
652 | return false; |
653 | |
654 | const FlatSetType sil_ordered(ordered_unique_range, il); |
655 | if(sil_ordered != expected) |
656 | return false; |
657 | |
658 | FlatSetType sil_assign = {99}; |
659 | sil_assign = il; |
660 | if(sil_assign != expected) |
661 | return false; |
662 | } |
663 | { |
664 | FlatSetType sil; |
665 | sil.insert(il); |
666 | if(sil != expected) |
667 | return false; |
668 | } |
669 | return true; |
670 | #endif |
671 | return true; |
672 | } |
673 | |
674 | struct boost_container_flat_set; |
675 | struct boost_container_flat_multiset; |
676 | |
677 | namespace boost { |
678 | namespace container { |
679 | namespace test { |
680 | |
681 | template<> |
682 | struct alloc_propagate_base<boost_container_flat_set> |
683 | { |
684 | template <class T, class Allocator> |
685 | struct apply |
686 | { |
687 | typedef boost::container::flat_set<T, std::less<T>, Allocator> type; |
688 | }; |
689 | }; |
690 | |
691 | template<> |
692 | struct alloc_propagate_base<boost_container_flat_multiset> |
693 | { |
694 | template <class T, class Allocator> |
695 | struct apply |
696 | { |
697 | typedef boost::container::flat_multiset<T, std::less<T>, Allocator> type; |
698 | }; |
699 | }; |
700 | |
701 | }}} //boost::container::test |
702 | |
703 | int main() |
704 | { |
705 | using namespace boost::container::test; |
706 | |
707 | //Allocator argument container |
708 | { |
709 | flat_set<int> set_((flat_set<int>::allocator_type())); |
710 | flat_multiset<int> multiset_((flat_multiset<int>::allocator_type())); |
711 | } |
712 | //Now test move semantics |
713 | { |
714 | test_move<flat_set<recursive_flat_set> >(); |
715 | test_move<flat_multiset<recursive_flat_multiset> >(); |
716 | } |
717 | //Now test nth/index_of |
718 | { |
719 | flat_set<int> set; |
720 | flat_multiset<int> mset; |
721 | |
722 | set.insert(x: 0); |
723 | set.insert(x: 1); |
724 | set.insert(x: 2); |
725 | mset.insert(x: 0); |
726 | mset.insert(x: 1); |
727 | mset.insert(x: 2); |
728 | if(!boost::container::test::test_nth_index_of(c&: set)) |
729 | return 1; |
730 | if(!boost::container::test::test_nth_index_of(c&: mset)) |
731 | return 1; |
732 | } |
733 | |
734 | //////////////////////////////////// |
735 | // Ordered insertion test |
736 | //////////////////////////////////// |
737 | if(!flat_tree_ordered_insertion_test()){ |
738 | return 1; |
739 | } |
740 | |
741 | //////////////////////////////////// |
742 | // Constructor Template Auto Deduction test |
743 | //////////////////////////////////// |
744 | if (!constructor_template_auto_deduction_test()) { |
745 | return 1; |
746 | } |
747 | |
748 | //////////////////////////////////// |
749 | // Extract/Adopt test |
750 | //////////////////////////////////// |
751 | if(!flat_tree_extract_adopt_test()){ |
752 | return 1; |
753 | } |
754 | |
755 | if (!boost::container::test::instantiate_constructors<flat_set<int>, flat_multiset<int> >()) |
756 | return 1; |
757 | |
758 | if(!test_heterogeneous_lookups()){ |
759 | return 1; |
760 | } |
761 | |
762 | if(!test_heterogeneous_lookup_by_partial_key()){ |
763 | return 1; |
764 | } |
765 | |
766 | //////////////////////////////////// |
767 | // Testing allocator implementations |
768 | //////////////////////////////////// |
769 | { |
770 | typedef std::set<int> MyStdSet; |
771 | typedef std::multiset<int> MyStdMultiSet; |
772 | |
773 | if (0 != test::set_test |
774 | < GetSetContainer<std::allocator<void> >::apply<int>::set_type |
775 | , MyStdSet |
776 | , GetSetContainer<std::allocator<void> >::apply<int>::multiset_type |
777 | , MyStdMultiSet>()) { |
778 | std::cout << "Error in set_test<std::allocator<void> >" << std::endl; |
779 | return 1; |
780 | } |
781 | |
782 | if (0 != test::set_test |
783 | < GetSetContainer<new_allocator<void> >::apply<int>::set_type |
784 | , MyStdSet |
785 | , GetSetContainer<new_allocator<void> >::apply<int>::multiset_type |
786 | , MyStdMultiSet>()) { |
787 | std::cout << "Error in set_test<new_allocator<void> >" << std::endl; |
788 | return 1; |
789 | } |
790 | |
791 | if (0 != test::set_test |
792 | < GetSetContainer<new_allocator<void> >::apply<test::movable_int>::set_type |
793 | , MyStdSet |
794 | , GetSetContainer<new_allocator<void> >::apply<test::movable_int>::multiset_type |
795 | , MyStdMultiSet>()) { |
796 | std::cout << "Error in set_test<new_allocator<void> >" << std::endl; |
797 | return 1; |
798 | } |
799 | |
800 | if (0 != test::set_test |
801 | < GetSetContainer<new_allocator<void> >::apply<test::copyable_int>::set_type |
802 | , MyStdSet |
803 | , GetSetContainer<new_allocator<void> >::apply<test::copyable_int>::multiset_type |
804 | , MyStdMultiSet>()) { |
805 | std::cout << "Error in set_test<new_allocator<void> >" << std::endl; |
806 | return 1; |
807 | } |
808 | |
809 | if (0 != test::set_test |
810 | < GetSetContainer<new_allocator<void> >::apply<test::movable_and_copyable_int>::set_type |
811 | , MyStdSet |
812 | , GetSetContainer<new_allocator<void> >::apply<test::movable_and_copyable_int>::multiset_type |
813 | , MyStdMultiSet>()) { |
814 | std::cout << "Error in set_test<new_allocator<void> >" << std::endl; |
815 | return 1; |
816 | } |
817 | } |
818 | |
819 | //////////////////////////////////// |
820 | // Emplace testing |
821 | //////////////////////////////////// |
822 | const test::EmplaceOptions SetOptions = (test::EmplaceOptions)(test::EMPLACE_HINT | test::EMPLACE_ASSOC); |
823 | |
824 | if(!boost::container::test::test_emplace<flat_set<test::EmplaceInt>, SetOptions>()) |
825 | return 1; |
826 | if(!boost::container::test::test_emplace<flat_multiset<test::EmplaceInt>, SetOptions>()) |
827 | return 1; |
828 | |
829 | if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for<flat_set<int> >()) |
830 | return 1; |
831 | |
832 | if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for<flat_multiset<int> >()) |
833 | return 1; |
834 | |
835 | //////////////////////////////////// |
836 | // Allocator propagation testing |
837 | //////////////////////////////////// |
838 | if(!boost::container::test::test_propagate_allocator<boost_container_flat_set>()) |
839 | return 1; |
840 | |
841 | if(!boost::container::test::test_propagate_allocator<boost_container_flat_multiset>()) |
842 | return 1; |
843 | |
844 | //////////////////////////////////// |
845 | // Iterator testing |
846 | //////////////////////////////////// |
847 | { |
848 | typedef boost::container::flat_set<int> cont_int; |
849 | cont_int a; a.insert(x: 0); a.insert(x: 1); a.insert(x: 2); |
850 | boost::intrusive::test::test_iterator_random< cont_int >(c&: a); |
851 | if(boost::report_errors() != 0) { |
852 | return 1; |
853 | } |
854 | } |
855 | { |
856 | typedef boost::container::flat_multiset<int> cont_int; |
857 | cont_int a; a.insert(x: 0); a.insert(x: 1); a.insert(x: 2); |
858 | boost::intrusive::test::test_iterator_random< cont_int >(c&: a); |
859 | if(boost::report_errors() != 0) { |
860 | return 1; |
861 | } |
862 | } |
863 | |
864 | //////////////////////////////////// |
865 | // has_trivial_destructor_after_move testing |
866 | //////////////////////////////////// |
867 | { |
868 | typedef boost::container::dtl::identity<int> key_of_value_t; |
869 | // flat_set, default |
870 | { |
871 | typedef boost::container::flat_set<int> cont; |
872 | typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, void> tree; |
873 | BOOST_CONTAINER_STATIC_ASSERT_MSG ( boost::has_trivial_destructor_after_move<cont>::value == |
874 | boost::has_trivial_destructor_after_move<tree>::value |
875 | , "has_trivial_destructor_after_move(flat_set, default) test failed" ); |
876 | } |
877 | // flat_set, vector |
878 | { |
879 | typedef boost::container::vector<int> alloc_or_cont_t; |
880 | typedef boost::container::flat_set<int, std::less<int>, alloc_or_cont_t> cont; |
881 | typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree; |
882 | BOOST_CONTAINER_STATIC_ASSERT_MSG ( boost::has_trivial_destructor_after_move<cont>::value == |
883 | boost::has_trivial_destructor_after_move<tree>::value |
884 | , "has_trivial_destructor_after_move(flat_set, vector) test failed" ); |
885 | } |
886 | // flat_set, std::vector |
887 | { |
888 | typedef std::vector<int> alloc_or_cont_t; |
889 | typedef boost::container::flat_set<int, std::less<int>, alloc_or_cont_t> cont; |
890 | typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree; |
891 | BOOST_CONTAINER_STATIC_ASSERT_MSG ( boost::has_trivial_destructor_after_move<cont>::value == |
892 | boost::has_trivial_destructor_after_move<tree>::value |
893 | , "has_trivial_destructor_after_move(flat_set, std::vector) test failed" ); |
894 | } |
895 | // flat_multiset, default |
896 | { |
897 | typedef boost::container::flat_multiset<int> cont; |
898 | typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, void> tree; |
899 | BOOST_CONTAINER_STATIC_ASSERT_MSG ( boost::has_trivial_destructor_after_move<cont>::value == |
900 | boost::has_trivial_destructor_after_move<tree>::value |
901 | , "has_trivial_destructor_after_move(flat_multiset, default) test failed" ); |
902 | } |
903 | // flat_multiset, vector |
904 | { |
905 | typedef boost::container::vector<int> alloc_or_cont_t; |
906 | typedef boost::container::flat_multiset<int, std::less<int>, alloc_or_cont_t> cont; |
907 | typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree; |
908 | BOOST_CONTAINER_STATIC_ASSERT_MSG ( boost::has_trivial_destructor_after_move<cont>::value == |
909 | boost::has_trivial_destructor_after_move<tree>::value |
910 | , "has_trivial_destructor_after_move(flat_multiset, vector) test failed" ); |
911 | } |
912 | // flat_multiset, std::vector |
913 | { |
914 | typedef std::vector<int> alloc_or_cont_t; |
915 | typedef boost::container::flat_multiset<int, std::less<int>, alloc_or_cont_t> cont; |
916 | typedef boost::container::dtl::flat_tree<int, key_of_value_t, std::less<int>, alloc_or_cont_t> tree; |
917 | BOOST_CONTAINER_STATIC_ASSERT_MSG ( boost::has_trivial_destructor_after_move<cont>::value == |
918 | boost::has_trivial_destructor_after_move<tree>::value |
919 | , "has_trivial_destructor_after_move(flat_multiset, std::vector) test failed" ); |
920 | } |
921 | } |
922 | |
923 | return 0; |
924 | } |
925 | |