• 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/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