• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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