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 <vector>
11
12 #include <boost/container/flat_map.hpp>
13 #include <boost/container/allocator.hpp>
14 #include <boost/container/detail/container_or_allocator_rebind.hpp>
15
16 #include "print_container.hpp"
17 #include "dummy_test_allocator.hpp"
18 #include "movable_int.hpp"
19 #include "map_test.hpp"
20 #include "propagate_allocator_test.hpp"
21 #include "container_common_tests.hpp"
22 #include "emplace_test.hpp"
23 #include "../../intrusive/test/iterator_test.hpp"
24
25 #include <map>
26 #include <utility>
27
28
29 using namespace boost::container;
30
31 class recursive_flat_map
32 {
33 public:
recursive_flat_map(const recursive_flat_map & c)34 recursive_flat_map(const recursive_flat_map &c)
35 : id_(c.id_), map_(c.map_)
36 {}
37
operator =(const recursive_flat_map & c)38 recursive_flat_map & operator =(const recursive_flat_map &c)
39 {
40 id_ = c.id_;
41 map_= c.map_;
42 return *this;
43 }
44
45 int id_;
46 flat_map<recursive_flat_map, recursive_flat_map> map_;
47 flat_map<recursive_flat_map, recursive_flat_map>::iterator it_;
48 flat_map<recursive_flat_map, recursive_flat_map>::const_iterator cit_;
49 flat_map<recursive_flat_map, recursive_flat_map>::reverse_iterator rit_;
50 flat_map<recursive_flat_map, recursive_flat_map>::const_reverse_iterator crit_;
51
operator <(const recursive_flat_map & a,const recursive_flat_map & b)52 friend bool operator< (const recursive_flat_map &a, const recursive_flat_map &b)
53 { return a.id_ < b.id_; }
54 };
55
56
57 class recursive_flat_multimap
58 {
59 public:
recursive_flat_multimap(const recursive_flat_multimap & c)60 recursive_flat_multimap(const recursive_flat_multimap &c)
61 : id_(c.id_), map_(c.map_)
62 {}
63
operator =(const recursive_flat_multimap & c)64 recursive_flat_multimap & operator =(const recursive_flat_multimap &c)
65 {
66 id_ = c.id_;
67 map_= c.map_;
68 return *this;
69 }
70 int id_;
71 flat_multimap<recursive_flat_multimap, recursive_flat_multimap> map_;
72 flat_multimap<recursive_flat_multimap, recursive_flat_multimap>::iterator it_;
73 flat_multimap<recursive_flat_multimap, recursive_flat_multimap>::const_iterator cit_;
74 flat_multimap<recursive_flat_multimap, recursive_flat_multimap>::reverse_iterator rit_;
75 flat_multimap<recursive_flat_multimap, recursive_flat_multimap>::const_reverse_iterator crit_;
76
operator <(const recursive_flat_multimap & a,const recursive_flat_multimap & b)77 friend bool operator< (const recursive_flat_multimap &a, const recursive_flat_multimap &b)
78 { return a.id_ < b.id_; }
79 };
80
81 template<class C>
test_move()82 void test_move()
83 {
84 //Now test move semantics
85 C original;
86 C move_ctor(boost::move(original));
87 C move_assign;
88 move_assign = boost::move(move_ctor);
89 move_assign.swap(original);
90 }
91
92
93 namespace boost{
94 namespace container {
95 namespace test{
96
flat_tree_ordered_insertion_test()97 bool flat_tree_ordered_insertion_test()
98 {
99 using namespace boost::container;
100 const std::size_t NumElements = 100;
101
102 //Ordered insertion multimap
103 {
104 std::multimap<int, int> int_mmap;
105 for(std::size_t i = 0; i != NumElements; ++i){
106 int_mmap.insert(std::multimap<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
107 }
108 //Construction insertion
109 flat_multimap<int, int> fmmap(ordered_range, int_mmap.begin(), int_mmap.end());
110 if(!CheckEqualContainers(int_mmap, fmmap))
111 return false;
112 //Insertion when empty
113 fmmap.clear();
114 fmmap.insert(ordered_range, int_mmap.begin(), int_mmap.end());
115 if(!CheckEqualContainers(int_mmap, fmmap))
116 return false;
117 //Re-insertion
118 fmmap.insert(ordered_range, int_mmap.begin(), int_mmap.end());
119 std::multimap<int, int> int_mmap2(int_mmap);
120 int_mmap2.insert(int_mmap.begin(), int_mmap.end());
121 if(!CheckEqualContainers(int_mmap2, fmmap))
122 return false;
123 //Re-re-insertion
124 fmmap.insert(ordered_range, int_mmap2.begin(), int_mmap2.end());
125 std::multimap<int, int> int_mmap4(int_mmap2);
126 int_mmap4.insert(int_mmap2.begin(), int_mmap2.end());
127 if(!CheckEqualContainers(int_mmap4, fmmap))
128 return false;
129 //Re-re-insertion of even
130 std::multimap<int, int> int_even_mmap;
131 for(std::size_t i = 0; i < NumElements; i+=2){
132 int_mmap.insert(std::multimap<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
133 }
134 fmmap.insert(ordered_range, int_even_mmap.begin(), int_even_mmap.end());
135 int_mmap4.insert(int_even_mmap.begin(), int_even_mmap.end());
136 if(!CheckEqualContainers(int_mmap4, fmmap))
137 return false;
138 }
139
140 //Ordered insertion map
141 {
142 std::map<int, int> int_map;
143 for(std::size_t i = 0; i != NumElements; ++i){
144 int_map.insert(std::map<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
145 }
146 //Construction insertion
147 flat_map<int, int> fmap(ordered_unique_range, int_map.begin(), int_map.end());
148 if(!CheckEqualContainers(int_map, fmap))
149 return false;
150 //Insertion when empty
151 fmap.clear();
152 fmap.insert(ordered_unique_range, int_map.begin(), int_map.end());
153 if(!CheckEqualContainers(int_map, fmap))
154 return false;
155 //Re-insertion
156 fmap.insert(ordered_unique_range, int_map.begin(), int_map.end());
157 std::map<int, int> int_map2(int_map);
158 int_map2.insert(int_map.begin(), int_map.end());
159 if(!CheckEqualContainers(int_map2, fmap))
160 return false;
161 //Re-re-insertion
162 fmap.insert(ordered_unique_range, int_map2.begin(), int_map2.end());
163 std::map<int, int> int_map4(int_map2);
164 int_map4.insert(int_map2.begin(), int_map2.end());
165 if(!CheckEqualContainers(int_map4, fmap))
166 return false;
167 //Re-re-insertion of even
168 std::map<int, int> int_even_map;
169 for(std::size_t i = 0; i < NumElements; i+=2){
170 int_map.insert(std::map<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
171 }
172 fmap.insert(ordered_unique_range, int_even_map.begin(), int_even_map.end());
173 int_map4.insert(int_even_map.begin(), int_even_map.end());
174 if(!CheckEqualContainers(int_map4, fmap))
175 return false;
176 }
177
178 return true;
179 }
180
constructor_template_auto_deduction_test()181 bool constructor_template_auto_deduction_test()
182 {
183
184 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
185 using namespace boost::container;
186 const std::size_t NumElements = 100;
187 {
188 std::map<int, int> int_map;
189 for(std::size_t i = 0; i != NumElements; ++i){
190 int_map.insert(std::map<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
191 }
192 std::multimap<int, int> int_mmap;
193 for (std::size_t i = 0; i != NumElements; ++i) {
194 int_mmap.insert(std::multimap<int, int>::value_type(static_cast<int>(i), static_cast<int>(i)));
195 }
196
197 typedef std::less<int> comp_int_t;
198 typedef std::allocator<std::pair<int, int> > alloc_pair_int_t;
199
200 //range
201 {
202 auto fmap = flat_map(int_map.begin(), int_map.end());
203 if (!CheckEqualContainers(int_map, fmap))
204 return false;
205 auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end());
206 if (!CheckEqualContainers(int_mmap, fmmap))
207 return false;
208 }
209 //range+comp
210 {
211 auto fmap = flat_map(int_map.begin(), int_map.end(), comp_int_t());
212 if (!CheckEqualContainers(int_map, fmap))
213 return false;
214 auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end(), comp_int_t());
215 if (!CheckEqualContainers(int_mmap, fmmap))
216 return false;
217 }
218 //range+comp+alloc
219 {
220 auto fmap = flat_map(int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t());
221 if (!CheckEqualContainers(int_map, fmap))
222 return false;
223 auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t());
224 if (!CheckEqualContainers(int_mmap, fmmap))
225 return false;
226 }
227 //range+alloc
228 {
229 auto fmap = flat_map(int_map.begin(), int_map.end(), alloc_pair_int_t());
230 if (!CheckEqualContainers(int_map, fmap))
231 return false;
232 auto fmmap = flat_multimap(int_mmap.begin(), int_mmap.end(), alloc_pair_int_t());
233 if (!CheckEqualContainers(int_mmap, fmmap))
234 return false;
235 }
236
237 //ordered_unique_range / ordered_range
238
239 //range
240 {
241 auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end());
242 if(!CheckEqualContainers(int_map, fmap))
243 return false;
244 auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end());
245 if(!CheckEqualContainers(int_mmap, fmmap))
246 return false;
247 }
248 //range+comp
249 {
250 auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t());
251 if (!CheckEqualContainers(int_map, fmap))
252 return false;
253 auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t());
254 if (!CheckEqualContainers(int_mmap, fmmap))
255 return false;
256 }
257 //range+comp+alloc
258 {
259 auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end(), comp_int_t(), alloc_pair_int_t());
260 if (!CheckEqualContainers(int_map, fmap))
261 return false;
262 auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end(), comp_int_t(), alloc_pair_int_t());
263 if (!CheckEqualContainers(int_mmap, fmmap))
264 return false;
265 }
266 //range+alloc
267 {
268 auto fmap = flat_map(ordered_unique_range, int_map.begin(), int_map.end(),alloc_pair_int_t());
269 if (!CheckEqualContainers(int_map, fmap))
270 return false;
271 auto fmmap = flat_multimap(ordered_range, int_mmap.begin(), int_mmap.end(),alloc_pair_int_t());
272 if (!CheckEqualContainers(int_mmap, fmmap))
273 return false;
274 }
275 }
276 #endif
277
278 return true;
279 }
280
281 template< class RandomIt >
random_shuffle(RandomIt first,RandomIt last)282 void random_shuffle( RandomIt first, RandomIt last )
283 {
284 typedef typename boost::container::iterator_traits<RandomIt>::difference_type difference_type;
285 difference_type n = last - first;
286 for (difference_type i = n-1; i > 0; --i) {
287 difference_type j = std::rand() % (i+1);
288 if(j != i) {
289 boost::adl_move_swap(first[i], first[j]);
290 }
291 }
292 }
293
flat_tree_extract_adopt_test()294 bool flat_tree_extract_adopt_test()
295 {
296 using namespace boost::container;
297 const std::size_t NumElements = 100;
298
299 //extract/adopt map
300 {
301 //Construction insertion
302 flat_map<int, int> fmap;
303
304 for(std::size_t i = 0; i != NumElements; ++i){
305 fmap.emplace(static_cast<int>(i), -static_cast<int>(i));
306 }
307
308 flat_map<int, int> fmap_copy(fmap);
309 flat_map<int, int>::sequence_type seq(fmap.extract_sequence());
310 if(!fmap.empty())
311 return false;
312 if(!CheckEqualContainers(seq, fmap_copy))
313 return false;
314
315 seq.insert(seq.end(), fmap_copy.begin(), fmap_copy.end());
316 boost::container::test::random_shuffle(seq.begin(), seq.end());
317 fmap.adopt_sequence(boost::move(seq));
318 if(!CheckEqualContainers(fmap, fmap_copy))
319 return false;
320 }
321
322 //extract/adopt map, ordered_unique_range
323 {
324 //Construction insertion
325 flat_map<int, int> fmap;
326
327 for(std::size_t i = 0; i != NumElements; ++i){
328 fmap.emplace(static_cast<int>(i), -static_cast<int>(i));
329 }
330
331 flat_map<int, int> fmap_copy(fmap);
332 flat_map<int, int>::sequence_type seq(fmap.extract_sequence());
333 if(!fmap.empty())
334 return false;
335 if(!CheckEqualContainers(seq, fmap_copy))
336 return false;
337
338 fmap.adopt_sequence(ordered_unique_range, boost::move(seq));
339 if(!CheckEqualContainers(fmap, fmap_copy))
340 return false;
341 }
342
343 //extract/adopt multimap
344 {
345 //Construction insertion
346 flat_multimap<int, int> fmmap;
347
348 for(std::size_t i = 0; i != NumElements; ++i){
349 fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
350 fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
351 }
352
353 flat_multimap<int, int> fmmap_copy(fmmap);
354 flat_multimap<int, int>::sequence_type seq(fmmap.extract_sequence());
355 if(!fmmap.empty())
356 return false;
357 if(!CheckEqualContainers(seq, fmmap_copy))
358 return false;
359
360 boost::container::test::random_shuffle(seq.begin(), seq.end());
361 fmmap.adopt_sequence(boost::move(seq));
362 if(!CheckEqualContainers(fmmap, fmmap_copy))
363 return false;
364 }
365
366 //extract/adopt multimap, ordered_range
367 {
368 //Construction insertion
369 flat_multimap<int, int> fmmap;
370
371 for(std::size_t i = 0; i != NumElements; ++i){
372 fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
373 fmmap.emplace(static_cast<int>(i), -static_cast<int>(i));
374 }
375
376 flat_multimap<int, int> fmmap_copy(fmmap);
377 flat_multimap<int, int>::sequence_type seq(fmmap.extract_sequence());
378 if(!fmmap.empty())
379 return false;
380 if(!CheckEqualContainers(seq, fmmap_copy))
381 return false;
382
383 fmmap.adopt_sequence(ordered_range, boost::move(seq));
384 if(!CheckEqualContainers(fmmap, fmmap_copy))
385 return false;
386 }
387
388 return true;
389 }
390
391 }}}
392
393 template<class VoidAllocatorOrContainer>
394 struct GetMapContainer
395 {
396 template<class ValueType>
397 struct apply
398 {
399 typedef std::pair<ValueType, ValueType> type_t;
400 typedef flat_map< ValueType
401 , ValueType
402 , std::less<ValueType>
403 , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, type_t>::type
404 > map_type;
405
406 typedef flat_multimap< ValueType
407 , ValueType
408 , std::less<ValueType>
409 , typename boost::container::dtl::container_or_allocator_rebind<VoidAllocatorOrContainer, type_t>::type
410 > multimap_type;
411 };
412 };
413
414 struct boost_container_flat_map;
415 struct boost_container_flat_multimap;
416
417 namespace boost { namespace container { namespace test {
418
419 template<>
420 struct alloc_propagate_base<boost_container_flat_map>
421 {
422 template <class T, class Allocator>
423 struct apply
424 {
425 typedef typename boost::container::allocator_traits<Allocator>::
426 template portable_rebind_alloc<std::pair<T, T> >::type TypeAllocator;
427 typedef boost::container::flat_map<T, T, std::less<T>, TypeAllocator> type;
428 };
429 };
430
431 template<>
432 struct alloc_propagate_base<boost_container_flat_multimap>
433 {
434 template <class T, class Allocator>
435 struct apply
436 {
437 typedef typename boost::container::allocator_traits<Allocator>::
438 template portable_rebind_alloc<std::pair<T, T> >::type TypeAllocator;
439 typedef boost::container::flat_multimap<T, T, std::less<T>, TypeAllocator> type;
440 };
441 };
442
443 template <class Key, class T, class Compare, class Allocator>
444 struct get_real_stored_allocator<flat_map<Key, T, Compare, Allocator> >
445 {
446 typedef typename flat_map<Key, T, Compare, Allocator>::impl_stored_allocator_type type;
447 };
448
449 template <class Key, class T, class Compare, class Allocator>
450 struct get_real_stored_allocator<flat_multimap<Key, T, Compare, Allocator> >
451 {
452 typedef typename flat_multimap<Key, T, Compare, Allocator>::impl_stored_allocator_type type;
453 };
454
test_heterogeneous_lookups()455 bool test_heterogeneous_lookups()
456 {
457 BOOST_STATIC_ASSERT((dtl::is_transparent<less_transparent>::value));
458 BOOST_STATIC_ASSERT(!(dtl::is_transparent<std::less<int> >::value));
459 typedef flat_map<int, char, less_transparent> map_t;
460 typedef flat_multimap<int, char, less_transparent> mmap_t;
461 typedef map_t::value_type value_type;
462
463 map_t map1;
464 mmap_t mmap1;
465
466 const map_t &cmap1 = map1;
467 const mmap_t &cmmap1 = mmap1;
468
469 if(!map1.insert_or_assign(1, 'a').second)
470 return false;
471 if( map1.insert_or_assign(1, 'b').second)
472 return false;
473 if(!map1.insert_or_assign(2, 'c').second)
474 return false;
475 if( map1.insert_or_assign(2, 'd').second)
476 return false;
477 if(!map1.insert_or_assign(3, 'e').second)
478 return false;
479
480 if(map1.insert_or_assign(1, 'a').second)
481 return false;
482 if(map1.insert_or_assign(1, 'b').second)
483 return false;
484 if(map1.insert_or_assign(2, 'c').second)
485 return false;
486 if(map1.insert_or_assign(2, 'd').second)
487 return false;
488 if(map1.insert_or_assign(3, 'e').second)
489 return false;
490
491 mmap1.insert(value_type(1, 'a'));
492 mmap1.insert(value_type(1, 'b'));
493 mmap1.insert(value_type(2, 'c'));
494 mmap1.insert(value_type(2, 'd'));
495 mmap1.insert(value_type(3, 'e'));
496
497 const test::non_copymovable_int find_me(2);
498
499 //find
500 if(map1.find(find_me)->second != 'd')
501 return false;
502 if(cmap1.find(find_me)->second != 'd')
503 return false;
504 if(mmap1.find(find_me)->second != 'c')
505 return false;
506 if(cmmap1.find(find_me)->second != 'c')
507 return false;
508
509 //count
510 if(map1.count(find_me) != 1)
511 return false;
512 if(cmap1.count(find_me) != 1)
513 return false;
514 if(mmap1.count(find_me) != 2)
515 return false;
516 if(cmmap1.count(find_me) != 2)
517 return false;
518
519 //contains
520 if(!map1.contains(find_me))
521 return false;
522 if(!cmap1.contains(find_me))
523 return false;
524 if(!mmap1.contains(find_me))
525 return false;
526 if(!cmmap1.contains(find_me))
527 return false;
528
529 //lower_bound
530 if(map1.lower_bound(find_me)->second != 'd')
531 return false;
532 if(cmap1.lower_bound(find_me)->second != 'd')
533 return false;
534 if(mmap1.lower_bound(find_me)->second != 'c')
535 return false;
536 if(cmmap1.lower_bound(find_me)->second != 'c')
537 return false;
538
539 //upper_bound
540 if(map1.upper_bound(find_me)->second != 'e')
541 return false;
542 if(cmap1.upper_bound(find_me)->second != 'e')
543 return false;
544 if(mmap1.upper_bound(find_me)->second != 'e')
545 return false;
546 if(cmmap1.upper_bound(find_me)->second != 'e')
547 return false;
548
549 //equal_range
550 if(map1.equal_range(find_me).first->second != 'd')
551 return false;
552 if(cmap1.equal_range(find_me).second->second != 'e')
553 return false;
554 if(mmap1.equal_range(find_me).first->second != 'c')
555 return false;
556 if(cmmap1.equal_range(find_me).second->second != 'e')
557 return false;
558
559 return true;
560 }
561
562 // An ordered sequence of std:pair is also ordered by std::pair::first.
563 struct with_lookup_by_first
564 {
565 typedef void is_transparent;
operator ()boost::container::test::with_lookup_by_first566 inline bool operator()(std::pair<int, int> a, std::pair<int, int> b) const
567 {
568 return a < b;
569 }
operator ()boost::container::test::with_lookup_by_first570 inline bool operator()(std::pair<int, int> a, int first) const
571 {
572 return a.first < first;
573 }
operator ()boost::container::test::with_lookup_by_first574 inline bool operator()(int first, std::pair<int, int> b) const
575 {
576 return first < b.first;
577 }
578 };
579
test_heterogeneous_lookup_by_partial_key()580 bool test_heterogeneous_lookup_by_partial_key()
581 {
582 typedef flat_map<std::pair<int, int>,int, with_lookup_by_first> map_t;
583
584 map_t map1;
585 map1[std::pair<int, int>(0, 1)] = 3;
586 map1[std::pair<int, int>(0, 2)] = 3;
587
588 std::pair<map_t::iterator, map_t::iterator> const first_0_range = map1.equal_range(0);
589
590 if(2 != (first_0_range.second - first_0_range.first))
591 return false;
592
593 if(2 != map1.count(0))
594 return false;
595 return true;
596 }
597
598 }}} //namespace boost::container::test
599
main()600 int main()
601 {
602 using namespace boost::container::test;
603
604 //Allocator argument container
605 {
606 flat_map<int, int> map_((flat_map<int, int>::allocator_type()));
607 flat_multimap<int, int> multimap_((flat_multimap<int, int>::allocator_type()));
608 }
609 //Now test move semantics
610 {
611 test_move<flat_map<recursive_flat_map, recursive_flat_map> >();
612 test_move<flat_multimap<recursive_flat_multimap, recursive_flat_multimap> >();
613 }
614 //Now test nth/index_of
615 {
616 flat_map<int, int> map;
617 flat_multimap<int, int> mmap;
618
619 map.insert(std::pair<int, int>(0, 0));
620 map.insert(std::pair<int, int>(1, 0));
621 map.insert(std::pair<int, int>(2, 0));
622 mmap.insert(std::pair<int, int>(0, 0));
623 mmap.insert(std::pair<int, int>(1, 0));
624 mmap.insert(std::pair<int, int>(2, 0));
625 if(!boost::container::test::test_nth_index_of(map))
626 return 1;
627 if(!boost::container::test::test_nth_index_of(mmap))
628 return 1;
629 }
630
631 ////////////////////////////////////
632 // Ordered insertion test
633 ////////////////////////////////////
634 if(!flat_tree_ordered_insertion_test()){
635 return 1;
636 }
637
638 ////////////////////////////////////
639 // Constructor Template Auto Deduction test
640 ////////////////////////////////////
641 if(!constructor_template_auto_deduction_test()){
642 return 1;
643 }
644
645 ////////////////////////////////////
646 // Extract/Adopt test
647 ////////////////////////////////////
648 if(!flat_tree_extract_adopt_test()){
649 return 1;
650 }
651
652 if (!boost::container::test::instantiate_constructors<flat_map<int, int>, flat_multimap<int, int> >())
653 return 1;
654
655 if (!test_heterogeneous_lookups())
656 return 1;
657
658 if (!test_heterogeneous_lookup_by_partial_key())
659 return 1;
660
661 ////////////////////////////////////
662 // Testing allocator implementations
663 ////////////////////////////////////
664 {
665 typedef std::map<int, int> MyStdMap;
666 typedef std::multimap<int, int> MyStdMultiMap;
667
668 if (0 != test::map_test
669 < GetMapContainer<std::allocator<void> >::apply<int>::map_type
670 , MyStdMap
671 , GetMapContainer<std::allocator<void> >::apply<int>::multimap_type
672 , MyStdMultiMap>()) {
673 std::cout << "Error in map_test<std::allocator<void> >" << std::endl;
674 return 1;
675 }
676
677 if (0 != test::map_test
678 < GetMapContainer<new_allocator<void> >::apply<int>::map_type
679 , MyStdMap
680 , GetMapContainer<new_allocator<void> >::apply<int>::multimap_type
681 , MyStdMultiMap>()) {
682 std::cout << "Error in map_test<new_allocator<void> >" << std::endl;
683 return 1;
684 }
685
686 if (0 != test::map_test
687 < GetMapContainer<new_allocator<void> >::apply<test::movable_int>::map_type
688 , MyStdMap
689 , GetMapContainer<new_allocator<void> >::apply<test::movable_int>::multimap_type
690 , MyStdMultiMap>()) {
691 std::cout << "Error in map_test<new_allocator<void> >" << std::endl;
692 return 1;
693 }
694
695 if (0 != test::map_test
696 < GetMapContainer<new_allocator<void> >::apply<test::copyable_int>::map_type
697 , MyStdMap
698 , GetMapContainer<new_allocator<void> >::apply<test::copyable_int>::multimap_type
699 , MyStdMultiMap>()) {
700 std::cout << "Error in map_test<new_allocator<void> >" << std::endl;
701 return 1;
702 }
703
704 if (0 != test::map_test
705 < GetMapContainer<new_allocator<void> >::apply<test::movable_and_copyable_int>::map_type
706 , MyStdMap
707 , GetMapContainer<new_allocator<void> >::apply<test::movable_and_copyable_int>::multimap_type
708 , MyStdMultiMap>()) {
709 std::cout << "Error in map_test<new_allocator<void> >" << std::endl;
710 return 1;
711 }
712 }
713
714 if(!boost::container::test::test_map_support_for_initialization_list_for<flat_map<int, int> >())
715 return 1;
716
717 if (!boost::container::test::test_map_support_for_initialization_list_for<flat_multimap<int, int> >())
718 return 1;
719
720 ////////////////////////////////////
721 // Emplace testing
722 ////////////////////////////////////
723 const test::EmplaceOptions MapOptions = (test::EmplaceOptions)(test::EMPLACE_HINT_PAIR | test::EMPLACE_ASSOC_PAIR);
724
725 if(!boost::container::test::test_emplace<flat_map<test::EmplaceInt, test::EmplaceInt>, MapOptions>())
726 return 1;
727 if(!boost::container::test::test_emplace<flat_multimap<test::EmplaceInt, test::EmplaceInt>, MapOptions>())
728 return 1;
729
730 ////////////////////////////////////
731 // Allocator propagation testing
732 ////////////////////////////////////
733 if(!boost::container::test::test_propagate_allocator<boost_container_flat_map>())
734 return 1;
735
736 if(!boost::container::test::test_propagate_allocator<boost_container_flat_multimap>())
737 return 1;
738
739 ////////////////////////////////////
740 // Iterator testing
741 ////////////////////////////////////
742 {
743 typedef boost::container::flat_map<int, int> cont_int;
744 cont_int a; a.insert(cont_int::value_type(0, 9)); a.insert(cont_int::value_type(1, 9)); a.insert(cont_int::value_type(2, 9));
745 boost::intrusive::test::test_iterator_random< cont_int >(a);
746 if(boost::report_errors() != 0) {
747 return 1;
748 }
749 }
750 {
751 typedef boost::container::flat_multimap<int, int> cont_int;
752 cont_int a; a.insert(cont_int::value_type(0, 9)); a.insert(cont_int::value_type(1, 9)); a.insert(cont_int::value_type(2, 9));
753 boost::intrusive::test::test_iterator_random< cont_int >(a);
754 if(boost::report_errors() != 0) {
755 return 1;
756 }
757 }
758
759 ////////////////////////////////////
760 // has_trivial_destructor_after_move testing
761 ////////////////////////////////////
762 {
763 typedef boost::container::dtl::pair<int, int> value_t;
764 typedef boost::container::dtl::select1st<int> key_of_value_t;
765 // flat_map, default
766 {
767 typedef boost::container::new_allocator<value_t> alloc_or_cont_t;
768 typedef boost::container::flat_map<int, int> cont;
769 typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
770 if (boost::has_trivial_destructor_after_move<cont>::value !=
771 boost::has_trivial_destructor_after_move<tree>::value) {
772 std::cerr << "has_trivial_destructor_after_move(flat_map, default) test failed" << std::endl;
773 return 1;
774 }
775 }
776 // flat_map, vector
777 {
778 typedef boost::container::vector<value_t> alloc_or_cont_t;
779 typedef boost::container::flat_map<int, int, std::less<int>, alloc_or_cont_t> cont;
780 typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
781 if (boost::has_trivial_destructor_after_move<cont>::value !=
782 boost::has_trivial_destructor_after_move<tree>::value) {
783 std::cerr << "has_trivial_destructor_after_move(flat_map, vector) test failed" << std::endl;
784 return 1;
785 }
786 }
787 // flat_map, std::vector
788 {
789 typedef std::vector<value_t> alloc_or_cont_t;
790 typedef boost::container::flat_map<int, int, std::less<int>, alloc_or_cont_t> cont;
791 typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
792 if (boost::has_trivial_destructor_after_move<cont>::value !=
793 boost::has_trivial_destructor_after_move<tree>::value) {
794 std::cerr << "has_trivial_destructor_after_move(flat_map, std::vector) test failed" << std::endl;
795 return 1;
796 }
797 }
798 // flat_multimap, default
799 {
800 typedef boost::container::new_allocator<value_t> alloc_or_cont_t;
801 typedef boost::container::flat_multimap<int, int> cont;
802 typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
803 if (boost::has_trivial_destructor_after_move<cont>::value !=
804 boost::has_trivial_destructor_after_move<tree>::value) {
805 std::cerr << "has_trivial_destructor_after_move(flat_multimap, default) test failed" << std::endl;
806 return 1;
807 }
808 }
809 // flat_multimap, vector
810 {
811 typedef boost::container::vector<value_t> alloc_or_cont_t;
812 typedef boost::container::flat_multimap<int, int, std::less<int>, alloc_or_cont_t> cont;
813 typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
814 if (boost::has_trivial_destructor_after_move<cont>::value !=
815 boost::has_trivial_destructor_after_move<tree>::value) {
816 std::cerr << "has_trivial_destructor_after_move(flat_multimap, vector) test failed" << std::endl;
817 return 1;
818 }
819 }
820 // flat_multimap, std::vector
821 {
822 typedef std::vector<value_t> alloc_or_cont_t;
823 typedef boost::container::flat_multimap<int, int, std::less<int>, alloc_or_cont_t> cont;
824 typedef boost::container::dtl::flat_tree<value_t, key_of_value_t, std::less<int>, alloc_or_cont_t> tree;
825 if (boost::has_trivial_destructor_after_move<cont>::value !=
826 boost::has_trivial_destructor_after_move<tree>::value) {
827 std::cerr << "has_trivial_destructor_after_move(flat_multimap, std::vector) test failed" << std::endl;
828 return 1;
829 }
830 }
831 }
832
833 return 0;
834 }
835