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 | #include <boost/container/map.hpp> |
11 | #include <boost/container/adaptive_pool.hpp> |
12 | |
13 | #include <map> |
14 | |
15 | #include "print_container.hpp" |
16 | #include "movable_int.hpp" |
17 | #include "dummy_test_allocator.hpp" |
18 | #include "map_test.hpp" |
19 | #include "propagate_allocator_test.hpp" |
20 | #include "emplace_test.hpp" |
21 | #include "../../intrusive/test/iterator_test.hpp" |
22 | |
23 | using namespace boost::container; |
24 | |
25 | typedef std::pair<const test::movable_and_copyable_int, test::movable_and_copyable_int> pair_t; |
26 | |
27 | class recursive_map |
28 | { |
29 | public: |
30 | recursive_map() |
31 | {} |
32 | |
33 | recursive_map(const recursive_map &x) |
34 | : map_(x.map_) |
35 | {} |
36 | |
37 | recursive_map & operator=(const recursive_map &x) |
38 | { id_ = x.id_; map_ = x.map_; return *this; } |
39 | |
40 | int id_; |
41 | map<recursive_map, recursive_map> map_; |
42 | map<recursive_map, recursive_map>::iterator it_; |
43 | map<recursive_map, recursive_map>::const_iterator cit_; |
44 | map<recursive_map, recursive_map>::reverse_iterator rit_; |
45 | map<recursive_map, recursive_map>::const_reverse_iterator crit_; |
46 | |
47 | friend bool operator< (const recursive_map &a, const recursive_map &b) |
48 | { return a.id_ < b.id_; } |
49 | }; |
50 | |
51 | class recursive_multimap |
52 | { |
53 | public: |
54 | recursive_multimap() |
55 | {} |
56 | |
57 | recursive_multimap(const recursive_multimap &x) |
58 | : multimap_(x.multimap_) |
59 | {} |
60 | |
61 | recursive_multimap & operator=(const recursive_multimap &x) |
62 | { id_ = x.id_; multimap_ = x.multimap_; return *this; } |
63 | |
64 | int id_; |
65 | multimap<recursive_multimap, recursive_multimap> multimap_; |
66 | multimap<recursive_multimap, recursive_multimap>::iterator it_; |
67 | multimap<recursive_multimap, recursive_multimap>::const_iterator cit_; |
68 | multimap<recursive_multimap, recursive_multimap>::reverse_iterator rit_; |
69 | multimap<recursive_multimap, recursive_multimap>::const_reverse_iterator crit_; |
70 | |
71 | friend bool operator< (const recursive_multimap &a, const recursive_multimap &b) |
72 | { return a.id_ < b.id_; } |
73 | }; |
74 | |
75 | template<class C> |
76 | void test_move() |
77 | { |
78 | //Now test move semantics |
79 | C original; |
80 | original.emplace(); |
81 | C move_ctor(boost::move(original)); |
82 | C move_assign; |
83 | move_assign.emplace(); |
84 | move_assign = boost::move(move_ctor); |
85 | move_assign.swap(original); |
86 | } |
87 | |
88 | bool node_type_test() |
89 | { |
90 | using namespace boost::container; |
91 | { |
92 | typedef map<test::movable_int, test::movable_int> map_type; |
93 | map_type src; |
94 | { |
95 | test::movable_int mv_1(1), mv_2(2), mv_3(3), mv_11(11), mv_12(12), mv_13(13); |
96 | src.try_emplace(k: boost::move(t&: mv_1), args: boost::move(t&: mv_11)); |
97 | src.try_emplace(k: boost::move(t&: mv_2), args: boost::move(t&: mv_12)); |
98 | src.try_emplace(k: boost::move(t&: mv_3), args: boost::move(t&: mv_13)); |
99 | } |
100 | if(src.size() != 3) |
101 | return false; |
102 | |
103 | map_type dst; |
104 | { |
105 | test::movable_int mv_3(3), mv_33(33); |
106 | dst.try_emplace(k: boost::move(t&: mv_3), args: boost::move(t&: mv_33)); |
107 | } |
108 | |
109 | if(dst.size() != 1) |
110 | return false; |
111 | |
112 | const test::movable_int mv_1(1); |
113 | const test::movable_int mv_2(2); |
114 | const test::movable_int mv_3(3); |
115 | const test::movable_int mv_33(33); |
116 | const test::movable_int mv_13(13); |
117 | map_type::insert_return_type r; |
118 | |
119 | r = dst.insert(nh: src.extract(k: mv_33)); // Key version, try to insert empty node |
120 | if(! (r.position == dst.end() && r.inserted == false && r.node.empty()) ) |
121 | return false; |
122 | r = dst.insert(nh: src.extract(position: src.find(k: mv_1))); // Iterator version, successful |
123 | if(! (r.position == dst.find(k: mv_1) && r.inserted == true && r.node.empty()) ) |
124 | return false; |
125 | r = dst.insert(hint: dst.begin(), nh: src.extract(k: mv_2)); // Key type version, successful |
126 | if(! (r.position == dst.find(k: mv_2) && r.inserted == true && r.node.empty()) ) |
127 | return false; |
128 | r = dst.insert(nh: src.extract(k: mv_3)); // Key type version, unsuccessful |
129 | |
130 | if(!src.empty()) |
131 | return false; |
132 | if(dst.size() != 3) |
133 | return false; |
134 | if(! (r.position == dst.find(k: mv_3) && r.inserted == false && r.node.key() == mv_3 && r.node.mapped() == mv_13) ) |
135 | return false; |
136 | } |
137 | |
138 | { |
139 | typedef multimap<test::movable_int, test::movable_int> multimap_type; |
140 | multimap_type src; |
141 | { |
142 | test::movable_int mv_1(1), mv_2(2), mv_3(3), mv_3bis(3), mv_11(11), mv_12(12), mv_13(13), mv_23(23); |
143 | src.emplace(args: boost::move(t&: mv_1), args: boost::move(t&: mv_11)); |
144 | src.emplace(args: boost::move(t&: mv_2), args: boost::move(t&: mv_12)); |
145 | src.emplace(args: boost::move(t&: mv_3), args: boost::move(t&: mv_13)); |
146 | src.emplace_hint(p: src.begin(), args: boost::move(t&: mv_3bis), args: boost::move(t&: mv_23)); |
147 | } |
148 | if(src.size() != 4) |
149 | return false; |
150 | |
151 | multimap_type dst; |
152 | { |
153 | test::movable_int mv_3(3), mv_33(33); |
154 | dst.emplace(args: boost::move(t&: mv_3), args: boost::move(t&: mv_33)); |
155 | } |
156 | |
157 | if(dst.size() != 1) |
158 | return false; |
159 | |
160 | const test::movable_int mv_1(1); |
161 | const test::movable_int mv_2(2); |
162 | const test::movable_int mv_3(3); |
163 | const test::movable_int mv_4(4); |
164 | const test::movable_int mv_33(33); |
165 | const test::movable_int mv_13(13); |
166 | const test::movable_int mv_23(23); |
167 | multimap_type::iterator r; |
168 | |
169 | multimap_type::node_type nt(src.extract(k: mv_3)); |
170 | r = dst.insert(hint: dst.begin(), nh: boost::move(t&: nt)); |
171 | if(! (r->first == mv_3 && r->second == mv_23 && dst.find(k: mv_3) == r && nt.empty()) ) |
172 | return false; |
173 | |
174 | nt = src.extract(position: src.find(k: mv_1)); |
175 | r = dst.insert(nh: boost::move(t&: nt)); // Iterator version, successful |
176 | if(! (r->first == mv_1 && nt.empty()) ) |
177 | return false; |
178 | |
179 | nt = src.extract(k: mv_2); |
180 | r = dst.insert(nh: boost::move(t&: nt)); // Key type version, successful |
181 | if(! (r->first == mv_2 && nt.empty()) ) |
182 | return false; |
183 | |
184 | r = dst.insert(nh: src.extract(k: mv_3)); // Key type version, successful |
185 | if(! (r->first == mv_3 && r->second == mv_13 && r == --multimap_type::iterator(dst.upper_bound(k: mv_3)) && nt.empty()) ) |
186 | return false; |
187 | |
188 | r = dst.insert(nh: src.extract(k: mv_4)); // Key type version, unsuccessful |
189 | if(! (r == dst.end()) ) |
190 | return false; |
191 | |
192 | if(!src.empty()) |
193 | return false; |
194 | if(dst.size() != 5) |
195 | return false; |
196 | } |
197 | return true; |
198 | } |
199 | |
200 | template<class VoidAllocator, boost::container::tree_type_enum tree_type_value> |
201 | struct GetAllocatorMap |
202 | { |
203 | template<class ValueType> |
204 | struct apply |
205 | { |
206 | typedef map< ValueType |
207 | , ValueType |
208 | , std::less<ValueType> |
209 | , typename allocator_traits<VoidAllocator> |
210 | ::template portable_rebind_alloc< std::pair<const ValueType, ValueType> >::type |
211 | , typename boost::container::tree_assoc_options |
212 | < boost::container::tree_type<tree_type_value> |
213 | >::type |
214 | > map_type; |
215 | |
216 | typedef multimap< ValueType |
217 | , ValueType |
218 | , std::less<ValueType> |
219 | , typename allocator_traits<VoidAllocator> |
220 | ::template portable_rebind_alloc< std::pair<const ValueType, ValueType> >::type |
221 | , typename boost::container::tree_assoc_options |
222 | < boost::container::tree_type<tree_type_value> |
223 | >::type |
224 | > multimap_type; |
225 | }; |
226 | }; |
227 | |
228 | struct boost_container_map; |
229 | struct boost_container_multimap; |
230 | |
231 | namespace boost { namespace container { namespace test { |
232 | |
233 | template<> |
234 | struct alloc_propagate_base<boost_container_map> |
235 | { |
236 | template <class T, class Allocator> |
237 | struct apply |
238 | { |
239 | typedef typename boost::container::allocator_traits<Allocator>:: |
240 | template portable_rebind_alloc<std::pair<const T, T> >::type TypeAllocator; |
241 | typedef boost::container::map<T, T, std::less<T>, TypeAllocator> type; |
242 | }; |
243 | }; |
244 | |
245 | template<> |
246 | struct alloc_propagate_base<boost_container_multimap> |
247 | { |
248 | template <class T, class Allocator> |
249 | struct apply |
250 | { |
251 | typedef typename boost::container::allocator_traits<Allocator>:: |
252 | template portable_rebind_alloc<std::pair<const T, T> >::type TypeAllocator; |
253 | typedef boost::container::multimap<T, T, std::less<T>, TypeAllocator> type; |
254 | }; |
255 | }; |
256 | |
257 | void test_merge_from_different_comparison() |
258 | { |
259 | map<int, int> map1; |
260 | map<int, int, std::greater<int> > map2; |
261 | map1.merge(source&: map2); |
262 | } |
263 | |
264 | bool test_heterogeneous_lookups() |
265 | { |
266 | typedef map<int, char, less_transparent> map_t; |
267 | typedef multimap<int, char, less_transparent> mmap_t; |
268 | typedef map_t::value_type value_type; |
269 | |
270 | map_t map1; |
271 | mmap_t mmap1; |
272 | |
273 | const map_t &cmap1 = map1; |
274 | const mmap_t &cmmap1 = mmap1; |
275 | |
276 | if(!map1.insert_or_assign(k: 1, obj: 'a').second) |
277 | return false; |
278 | if( map1.insert_or_assign(k: 1, obj: 'b').second) |
279 | return false; |
280 | if(!map1.insert_or_assign(k: 2, obj: 'c').second) |
281 | return false; |
282 | if( map1.insert_or_assign(k: 2, obj: 'd').second) |
283 | return false; |
284 | if(!map1.insert_or_assign(k: 3, obj: 'e').second) |
285 | return false; |
286 | |
287 | if(map1.insert_or_assign(k: 1, obj: 'a').second) |
288 | return false; |
289 | if(map1.insert_or_assign(k: 1, obj: 'b').second) |
290 | return false; |
291 | if(map1.insert_or_assign(k: 2, obj: 'c').second) |
292 | return false; |
293 | if(map1.insert_or_assign(k: 2, obj: 'd').second) |
294 | return false; |
295 | if(map1.insert_or_assign(k: 3, obj: 'e').second) |
296 | return false; |
297 | |
298 | mmap1.insert(x: value_type(1, 'a')); |
299 | mmap1.insert(x: value_type(1, 'b')); |
300 | mmap1.insert(x: value_type(2, 'c')); |
301 | mmap1.insert(x: value_type(2, 'd')); |
302 | mmap1.insert(x: value_type(3, 'e')); |
303 | |
304 | const test::non_copymovable_int find_me(2); |
305 | |
306 | //find |
307 | if(map1.find(k: find_me)->second != 'd') |
308 | return false; |
309 | if(cmap1.find(k: find_me)->second != 'd') |
310 | return false; |
311 | if(mmap1.find(k: find_me)->second != 'c') |
312 | return false; |
313 | if(cmmap1.find(k: find_me)->second != 'c') |
314 | return false; |
315 | |
316 | //count |
317 | if(map1.count(x: find_me) != 1) |
318 | return false; |
319 | if(cmap1.count(x: find_me) != 1) |
320 | return false; |
321 | if(mmap1.count(k: find_me) != 2) |
322 | return false; |
323 | if(cmmap1.count(k: find_me) != 2) |
324 | return false; |
325 | |
326 | //contains |
327 | if(!map1.contains(x: find_me)) |
328 | return false; |
329 | if(!cmap1.contains(x: find_me)) |
330 | return false; |
331 | if(!mmap1.contains(x: find_me)) |
332 | return false; |
333 | if(!cmmap1.contains(x: find_me)) |
334 | return false; |
335 | |
336 | //lower_bound |
337 | if(map1.lower_bound(k: find_me)->second != 'd') |
338 | return false; |
339 | if(cmap1.lower_bound(k: find_me)->second != 'd') |
340 | return false; |
341 | if(mmap1.lower_bound(k: find_me)->second != 'c') |
342 | return false; |
343 | if(cmmap1.lower_bound(k: find_me)->second != 'c') |
344 | return false; |
345 | |
346 | //upper_bound |
347 | if(map1.upper_bound(k: find_me)->second != 'e') |
348 | return false; |
349 | if(cmap1.upper_bound(k: find_me)->second != 'e') |
350 | return false; |
351 | if(mmap1.upper_bound(k: find_me)->second != 'e') |
352 | return false; |
353 | if(cmmap1.upper_bound(k: find_me)->second != 'e') |
354 | return false; |
355 | |
356 | //equal_range |
357 | if(map1.equal_range(k: find_me).first->second != 'd') |
358 | return false; |
359 | if(cmap1.equal_range(k: find_me).second->second != 'e') |
360 | return false; |
361 | if(mmap1.equal_range(k: find_me).first->second != 'c') |
362 | return false; |
363 | if(cmmap1.equal_range(k: find_me).second->second != 'e') |
364 | return false; |
365 | |
366 | return true; |
367 | } |
368 | |
369 | bool constructor_template_auto_deduction_test() |
370 | { |
371 | |
372 | #ifndef BOOST_CONTAINER_NO_CXX17_CTAD |
373 | using namespace boost::container; |
374 | const std::size_t NumElements = 100; |
375 | { |
376 | std::map<int, int> int_map; |
377 | for(std::size_t i = 0; i != NumElements; ++i){ |
378 | int_map.insert(x: std::map<int, int>::value_type(static_cast<int>(i), static_cast<int>(i))); |
379 | } |
380 | std::multimap<int, int> int_mmap; |
381 | for (std::size_t i = 0; i != NumElements; ++i) { |
382 | int_mmap.insert(x: std::multimap<int, int>::value_type(static_cast<int>(i), static_cast<int>(i))); |
383 | } |
384 | |
385 | typedef std::less<int> comp_int_t; |
386 | typedef std::allocator<std::pair<const int, int> > alloc_pair_int_t; |
387 | |
388 | //range |
389 | { |
390 | auto fmap = map(int_map.begin(), int_map.end()); |
391 | if (!CheckEqualContainers(cont_a: int_map, cont_b: fmap)) |
392 | return false; |
393 | auto fmmap = multimap(int_mmap.begin(), int_mmap.end()); |
394 | if (!CheckEqualContainers(cont_a: int_mmap, cont_b: fmmap)) |
395 | return false; |
396 | } |
397 | //range+comp |
398 | { |
399 | auto fmap = map(int_map.begin(), int_map.end(), comp_int_t()); |
400 | if (!CheckEqualContainers(cont_a: int_map, cont_b: fmap)) |
401 | return false; |
402 | auto fmmap = multimap(int_mmap.begin(), int_mmap.end(), comp_int_t()); |
403 | if (!CheckEqualContainers(cont_a: int_mmap, cont_b: fmmap)) |
404 | return false; |
405 | } |
406 | //range+comp+alloc |
407 | { |
408 | auto fmap = map(int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t()); |
409 | if (!CheckEqualContainers(cont_a: int_map, cont_b: fmap)) |
410 | return false; |
411 | auto fmmap = multimap(int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t()); |
412 | if (!CheckEqualContainers(cont_a: int_mmap, cont_b: fmmap)) |
413 | return false; |
414 | } |
415 | //range+alloc |
416 | { |
417 | auto fmap = map(int_map.begin(), int_map.end(), alloc_pair_int_t()); |
418 | if (!CheckEqualContainers(cont_a: int_map, cont_b: fmap)) |
419 | return false; |
420 | auto fmmap = multimap(int_mmap.begin(), int_mmap.end(), alloc_pair_int_t()); |
421 | if (!CheckEqualContainers(cont_a: int_mmap, cont_b: fmmap)) |
422 | return false; |
423 | } |
424 | |
425 | //ordered_unique_range / ordered_range |
426 | |
427 | //range |
428 | { |
429 | auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end()); |
430 | if(!CheckEqualContainers(cont_a: int_map, cont_b: fmap)) |
431 | return false; |
432 | auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end()); |
433 | if(!CheckEqualContainers(cont_a: int_mmap, cont_b: fmmap)) |
434 | return false; |
435 | } |
436 | //range+comp |
437 | { |
438 | auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t()); |
439 | if (!CheckEqualContainers(cont_a: int_map, cont_b: fmap)) |
440 | return false; |
441 | auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t()); |
442 | if (!CheckEqualContainers(cont_a: int_mmap, cont_b: fmmap)) |
443 | return false; |
444 | } |
445 | //range+comp+alloc |
446 | { |
447 | auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t()); |
448 | if (!CheckEqualContainers(cont_a: int_map, cont_b: fmap)) |
449 | return false; |
450 | auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t()); |
451 | if (!CheckEqualContainers(cont_a: int_mmap, cont_b: fmmap)) |
452 | return false; |
453 | } |
454 | //range+alloc |
455 | { |
456 | auto fmap = map(ordered_unique_range, int_map.begin(), int_map.end(),alloc_pair_int_t()); |
457 | if (!CheckEqualContainers(cont_a: int_map, cont_b: fmap)) |
458 | return false; |
459 | auto fmmap = multimap(ordered_range, int_mmap.begin(), int_mmap.end(),alloc_pair_int_t()); |
460 | if (!CheckEqualContainers(cont_a: int_mmap, cont_b: fmmap)) |
461 | return false; |
462 | } |
463 | } |
464 | #endif |
465 | |
466 | return true; |
467 | } |
468 | |
469 | }}} //namespace boost::container::test |
470 | |
471 | int main () |
472 | { |
473 | //Recursive container instantiation |
474 | { |
475 | map<recursive_map, recursive_map> map_; |
476 | multimap<recursive_multimap, recursive_multimap> multimap_; |
477 | } |
478 | //Allocator argument container |
479 | { |
480 | map<int, int> map_((map<int, int>::allocator_type())); |
481 | multimap<int, int> multimap_((multimap<int, int>::allocator_type())); |
482 | } |
483 | //Now test move semantics |
484 | { |
485 | test_move<map<recursive_map, recursive_map> >(); |
486 | test_move<multimap<recursive_multimap, recursive_multimap> >(); |
487 | } |
488 | |
489 | //Test std::pair value type as tree has workarounds to make old std::pair |
490 | //implementations movable that can break things |
491 | { |
492 | boost::container::map<pair_t, pair_t> s; |
493 | std::pair<const pair_t,pair_t> p; |
494 | s.insert(x&: p); |
495 | s.emplace(args&: p); |
496 | } |
497 | |
498 | //////////////////////////////////// |
499 | // Testing allocator implementations |
500 | //////////////////////////////////// |
501 | { |
502 | typedef std::map<int, int> MyStdMap; |
503 | typedef std::multimap<int, int> MyStdMultiMap; |
504 | |
505 | if (0 != test::map_test |
506 | < GetAllocatorMap<std::allocator<void>, red_black_tree>::apply<int>::map_type |
507 | , MyStdMap |
508 | , GetAllocatorMap<std::allocator<void>, red_black_tree>::apply<int>::multimap_type |
509 | , MyStdMultiMap>()) { |
510 | std::cout << "Error in map_test<std::allocator<void>, red_black_tree>" << std::endl; |
511 | return 1; |
512 | } |
513 | |
514 | if (0 != test::map_test |
515 | < GetAllocatorMap<new_allocator<void>, avl_tree>::apply<int>::map_type |
516 | , MyStdMap |
517 | , GetAllocatorMap<new_allocator<void>, avl_tree>::apply<int>::multimap_type |
518 | , MyStdMultiMap>()) { |
519 | std::cout << "Error in map_test<new_allocator<void>, avl_tree>" << std::endl; |
520 | return 1; |
521 | } |
522 | |
523 | if (0 != test::map_test |
524 | < GetAllocatorMap<adaptive_pool<void>, scapegoat_tree>::apply<int>::map_type |
525 | , MyStdMap |
526 | , GetAllocatorMap<adaptive_pool<void>, scapegoat_tree>::apply<int>::multimap_type |
527 | , MyStdMultiMap>()) { |
528 | std::cout << "Error in map_test<adaptive_pool<void>, scapegoat_tree>" << std::endl; |
529 | return 1; |
530 | } |
531 | |
532 | /////////// |
533 | |
534 | if (0 != test::map_test |
535 | < GetAllocatorMap<new_allocator<void>, splay_tree>::apply<test::movable_int>::map_type |
536 | , MyStdMap |
537 | , GetAllocatorMap<new_allocator<void>, splay_tree>::apply<test::movable_int>::multimap_type |
538 | , MyStdMultiMap>()) { |
539 | std::cout << "Error in map_test<new_allocator<void>, splay_tree>" << std::endl; |
540 | return 1; |
541 | } |
542 | |
543 | if (0 != test::map_test |
544 | < GetAllocatorMap<new_allocator<void>, red_black_tree>::apply<test::copyable_int>::map_type |
545 | , MyStdMap |
546 | , GetAllocatorMap<new_allocator<void>, red_black_tree>::apply<test::copyable_int>::multimap_type |
547 | , MyStdMultiMap>()) { |
548 | std::cout << "Error in map_test<new_allocator<void>, red_black_tree>" << std::endl; |
549 | return 1; |
550 | } |
551 | |
552 | if (0 != test::map_test |
553 | < GetAllocatorMap<new_allocator<void>, red_black_tree>::apply<test::movable_and_copyable_int>::map_type |
554 | , MyStdMap |
555 | , GetAllocatorMap<new_allocator<void>, red_black_tree>::apply<test::movable_and_copyable_int>::multimap_type |
556 | , MyStdMultiMap>()) { |
557 | std::cout << "Error in map_test<new_allocator<void>, red_black_tree>" << std::endl; |
558 | return 1; |
559 | } |
560 | } |
561 | |
562 | //////////////////////////////////// |
563 | // Emplace testing |
564 | //////////////////////////////////// |
565 | const test::EmplaceOptions MapOptions = (test::EmplaceOptions)(test::EMPLACE_HINT_PAIR | test::EMPLACE_ASSOC_PAIR); |
566 | if(!boost::container::test::test_emplace<map<test::EmplaceInt, test::EmplaceInt>, MapOptions>()) |
567 | return 1; |
568 | if(!boost::container::test::test_emplace<multimap<test::EmplaceInt, test::EmplaceInt>, MapOptions>()) |
569 | return 1; |
570 | |
571 | //////////////////////////////////// |
572 | // Allocator propagation testing |
573 | //////////////////////////////////// |
574 | if(!boost::container::test::test_propagate_allocator<boost_container_map>()) |
575 | return 1; |
576 | |
577 | if(!boost::container::test::test_propagate_allocator<boost_container_multimap>()) |
578 | return 1; |
579 | |
580 | if (!boost::container::test::test_map_support_for_initialization_list_for<map<int, int> >()) |
581 | return 1; |
582 | |
583 | if (!boost::container::test::test_map_support_for_initialization_list_for<multimap<int, int> >()) |
584 | return 1; |
585 | |
586 | //////////////////////////////////// |
587 | // Iterator testing |
588 | //////////////////////////////////// |
589 | { |
590 | typedef boost::container::map<int, int> cont_int; |
591 | cont_int a; a.insert(x: cont_int::value_type(0, 9)); a.insert(x: cont_int::value_type(1, 9)); a.insert(x: cont_int::value_type(2, 9)); |
592 | boost::intrusive::test::test_iterator_bidirectional< cont_int >(c&: a); |
593 | if(boost::report_errors() != 0) { |
594 | return 1; |
595 | } |
596 | } |
597 | { |
598 | typedef boost::container::multimap<int, int> cont_int; |
599 | cont_int a; a.insert(x: cont_int::value_type(0, 9)); a.insert(x: cont_int::value_type(1, 9)); a.insert(x: cont_int::value_type(2, 9)); |
600 | boost::intrusive::test::test_iterator_bidirectional< cont_int >(c&: a); |
601 | if(boost::report_errors() != 0) { |
602 | return 1; |
603 | } |
604 | } |
605 | |
606 | //////////////////////////////////// |
607 | // Node extraction/insertion testing functions |
608 | //////////////////////////////////// |
609 | if(!node_type_test()) |
610 | return 1; |
611 | |
612 | //////////////////////////////////// |
613 | // Constructor Template Auto Deduction test |
614 | //////////////////////////////////// |
615 | if (!test::constructor_template_auto_deduction_test()) { |
616 | return 1; |
617 | } |
618 | |
619 | if (!boost::container::test::instantiate_constructors<map<int, int>, multimap<int, int> >()) |
620 | return 1; |
621 | |
622 | test::test_merge_from_different_comparison(); |
623 | |
624 | if(!test::test_heterogeneous_lookups()) |
625 | return 1; |
626 | |
627 | //////////////////////////////////// |
628 | // Test optimize_size option |
629 | //////////////////////////////////// |
630 | // |
631 | // map |
632 | // |
633 | typedef map< int*, int*, std::less<int*>, std::allocator< std::pair<int *const, int*> > |
634 | , tree_assoc_options< optimize_size<false>, tree_type<red_black_tree> >::type > rbmap_size_optimized_no; |
635 | |
636 | typedef map< int*, int*, std::less<int*>, std::allocator< std::pair<int *const, int*> > |
637 | , tree_assoc_options< optimize_size<true>, tree_type<avl_tree> >::type > avlmap_size_optimized_yes; |
638 | // |
639 | // multimap |
640 | // |
641 | typedef multimap< int*, int*, std::less<int*>, std::allocator< std::pair<int *const, int*> > |
642 | , tree_assoc_options< optimize_size<true>, tree_type<red_black_tree> >::type > rbmmap_size_optimized_yes; |
643 | typedef multimap< int*, int*, std::less<int*>, std::allocator< std::pair<int *const, int*> > |
644 | , tree_assoc_options< optimize_size<false>, tree_type<avl_tree> >::type > avlmmap_size_optimized_no; |
645 | |
646 | BOOST_CONTAINER_STATIC_ASSERT(sizeof(rbmmap_size_optimized_yes) < sizeof(rbmap_size_optimized_no)); |
647 | BOOST_CONTAINER_STATIC_ASSERT(sizeof(avlmap_size_optimized_yes) < sizeof(avlmmap_size_optimized_no)); |
648 | |
649 | //////////////////////////////////// |
650 | // has_trivial_destructor_after_move testing |
651 | //////////////////////////////////// |
652 | { |
653 | typedef std::pair<const int, int> value_type; |
654 | // |
655 | // map |
656 | // |
657 | // default allocator |
658 | { |
659 | typedef boost::container::map<int, int> cont; |
660 | typedef boost::container::dtl::tree<value_type, int, std::less<int>, void, void> tree; |
661 | BOOST_CONTAINER_STATIC_ASSERT_MSG( |
662 | !(boost::has_trivial_destructor_after_move<cont>::value != |
663 | boost::has_trivial_destructor_after_move<tree>::value) |
664 | , "has_trivial_destructor_after_move(map, default allocator) test failed" ); |
665 | } |
666 | // std::allocator |
667 | { |
668 | typedef boost::container::map<int, int, std::less<int>, std::allocator<value_type> > cont; |
669 | typedef boost::container::dtl::tree<value_type, int, std::less<int>, std::allocator<value_type>, void> tree; |
670 | BOOST_CONTAINER_STATIC_ASSERT_MSG( |
671 | !(boost::has_trivial_destructor_after_move<cont>::value != |
672 | boost::has_trivial_destructor_after_move<tree>::value) |
673 | , "has_trivial_destructor_after_move(map, std::allocator) test failed" ); |
674 | } |
675 | // |
676 | // multimap |
677 | // |
678 | // default allocator |
679 | { |
680 | // default allocator |
681 | typedef boost::container::multimap<int, int> cont; |
682 | typedef boost::container::dtl::tree<value_type, int, std::less<int>, void, void> tree; |
683 | BOOST_CONTAINER_STATIC_ASSERT_MSG( |
684 | !(boost::has_trivial_destructor_after_move<cont>::value != |
685 | boost::has_trivial_destructor_after_move<tree>::value) |
686 | , "has_trivial_destructor_after_move(multimap, default allocator) test failed" ); |
687 | } |
688 | // std::allocator |
689 | { |
690 | typedef boost::container::multimap<int, int, std::less<int>, std::allocator<value_type> > cont; |
691 | typedef boost::container::dtl::tree<value_type, int, std::less<int>, std::allocator<value_type>, void> tree; |
692 | BOOST_CONTAINER_STATIC_ASSERT_MSG( |
693 | !(boost::has_trivial_destructor_after_move<cont>::value != |
694 | boost::has_trivial_destructor_after_move<tree>::value) |
695 | , "has_trivial_destructor_after_move(multimap, std::allocator) test failed" ); |
696 | } |
697 | } |
698 | |
699 | return 0; |
700 | } |
701 | |