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