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