1 //////////////////////////////////////////////////////////////////////////////
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)
7 // See http://www.boost.org/libs/container for documentation.
9 //////////////////////////////////////////////////////////////////////////////
10 #include <boost/container/detail/config_begin.hpp>
11 #include <boost/container/map.hpp>
12 #include <boost/container/adaptive_pool.hpp>
16 #include "print_container.hpp"
17 #include "movable_int.hpp"
18 #include "dummy_test_allocator.hpp"
19 #include "map_test.hpp"
20 #include "propagate_allocator_test.hpp"
21 #include "emplace_test.hpp"
22 #include "../../intrusive/test/iterator_test.hpp"
24 using namespace boost::container
;
26 typedef std::pair
<const test::movable_and_copyable_int
, test::movable_and_copyable_int
> pair_t
;
31 //Explicit instantiation to detect compilation errors
35 < test::movable_and_copyable_int
36 , test::movable_and_copyable_int
37 , std::less
<test::movable_and_copyable_int
>
38 , test::simple_allocator
< pair_t
>
42 < test::movable_and_copyable_int
43 , test::movable_and_copyable_int
44 , std::less
<test::movable_and_copyable_int
>
45 , std::allocator
< pair_t
>
49 < test::movable_and_copyable_int
50 , test::movable_and_copyable_int
51 , std::less
<test::movable_and_copyable_int
>
52 , adaptive_pool
< pair_t
>
55 template class multimap
56 < test::movable_and_copyable_int
57 , test::movable_and_copyable_int
58 , std::less
<test::movable_and_copyable_int
>
59 , std::allocator
< pair_t
>
62 namespace container_detail
{
64 //Instantiate base class as previous instantiations don't instantiate inherited members
67 , select1st
<test::movable_and_copyable_int
>
68 , std::less
<test::movable_and_copyable_int
>
69 , test::simple_allocator
<pair_t
>
75 , select1st
<test::movable_and_copyable_int
>
76 , std::less
<test::movable_and_copyable_int
>
77 , std::allocator
<pair_t
>
83 , select1st
<test::movable_and_copyable_int
>
84 , std::less
<test::movable_and_copyable_int
>
85 , adaptive_pool
<pair_t
>
89 } //container_detail {
96 recursive_map
& operator=(const recursive_map
&x
)
97 { id_
= x
.id_
; map_
= x
.map_
; return *this; }
100 map
<recursive_map
, recursive_map
> map_
;
101 map
<recursive_map
, recursive_map
>::iterator it_
;
102 map
<recursive_map
, recursive_map
>::const_iterator cit_
;
103 map
<recursive_map
, recursive_map
>::reverse_iterator rit_
;
104 map
<recursive_map
, recursive_map
>::const_reverse_iterator crit_
;
106 friend bool operator< (const recursive_map
&a
, const recursive_map
&b
)
107 { return a
.id_
< b
.id_
; }
110 class recursive_multimap
113 recursive_multimap
& operator=(const recursive_multimap
&x
)
114 { id_
= x
.id_
; multimap_
= x
.multimap_
; return *this; }
117 multimap
<recursive_multimap
, recursive_multimap
> multimap_
;
118 multimap
<recursive_multimap
, recursive_multimap
>::iterator it_
;
119 multimap
<recursive_multimap
, recursive_multimap
>::const_iterator cit_
;
120 multimap
<recursive_multimap
, recursive_multimap
>::reverse_iterator rit_
;
121 multimap
<recursive_multimap
, recursive_multimap
>::const_reverse_iterator crit_
;
123 friend bool operator< (const recursive_multimap
&a
, const recursive_multimap
&b
)
124 { return a
.id_
< b
.id_
; }
130 //Now test move semantics
133 C
move_ctor(boost::move(original
));
135 move_assign
.emplace();
136 move_assign
= boost::move(move_ctor
);
137 move_assign
.swap(original
);
140 bool node_type_test()
142 using namespace boost::container
;
144 typedef map
<test::movable_int
, test::movable_int
> map_type
;
147 test::movable_int
mv_1(1), mv_2(2), mv_3(3), mv_11(11), mv_12(12), mv_13(13);
148 src
.try_emplace(boost::move(mv_1
), boost::move(mv_11
));
149 src
.try_emplace(boost::move(mv_2
), boost::move(mv_12
));
150 src
.try_emplace(boost::move(mv_3
), boost::move(mv_13
));
157 test::movable_int
mv_3(3), mv_33(33);
158 dst
.try_emplace(boost::move(mv_3
), boost::move(mv_33
));
164 const test::movable_int
mv_1(1);
165 const test::movable_int
mv_2(2);
166 const test::movable_int
mv_3(3);
167 const test::movable_int
mv_33(33);
168 const test::movable_int
mv_13(13);
169 map_type::insert_return_type r
;
171 r
= dst
.insert(src
.extract(mv_33
)); // Key version, try to insert empty node
172 if(! (r
.position
== dst
.end() && r
.inserted
== false && r
.node
.empty()) )
174 r
= dst
.insert(src
.extract(src
.find(mv_1
))); // Iterator version, successful
175 if(! (r
.position
== dst
.find(mv_1
) && r
.inserted
== true && r
.node
.empty()) )
177 r
= dst
.insert(dst
.begin(), src
.extract(mv_2
)); // Key type version, successful
178 if(! (r
.position
== dst
.find(mv_2
) && r
.inserted
== true && r
.node
.empty()) )
180 r
= dst
.insert(src
.extract(mv_3
)); // Key type version, unsuccessful
186 if(! (r
.position
== dst
.find(mv_3
) && r
.inserted
== false && r
.node
.key() == mv_3
&& r
.node
.mapped() == mv_13
) )
191 typedef multimap
<test::movable_int
, test::movable_int
> multimap_type
;
194 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);
195 src
.emplace(boost::move(mv_1
), boost::move(mv_11
));
196 src
.emplace(boost::move(mv_2
), boost::move(mv_12
));
197 src
.emplace(boost::move(mv_3
), boost::move(mv_13
));
198 src
.emplace_hint(src
.begin(), boost::move(mv_3bis
), boost::move(mv_23
));
205 test::movable_int
mv_3(3), mv_33(33);
206 dst
.emplace(boost::move(mv_3
), boost::move(mv_33
));
212 const test::movable_int
mv_1(1);
213 const test::movable_int
mv_2(2);
214 const test::movable_int
mv_3(3);
215 const test::movable_int
mv_4(4);
216 const test::movable_int
mv_33(33);
217 const test::movable_int
mv_13(13);
218 const test::movable_int
mv_23(23);
219 multimap_type::iterator r
;
221 multimap_type::node_type
nt(src
.extract(mv_3
));
222 r
= dst
.insert(dst
.begin(), boost::move(nt
));
223 if(! (r
->first
== mv_3
&& r
->second
== mv_23
&& dst
.find(mv_3
) == r
&& nt
.empty()) )
226 nt
= src
.extract(src
.find(mv_1
));
227 r
= dst
.insert(boost::move(nt
)); // Iterator version, successful
228 if(! (r
->first
== mv_1
&& nt
.empty()) )
231 nt
= src
.extract(mv_2
);
232 r
= dst
.insert(boost::move(nt
)); // Key type version, successful
233 if(! (r
->first
== mv_2
&& nt
.empty()) )
236 r
= dst
.insert(src
.extract(mv_3
)); // Key type version, successful
237 if(! (r
->first
== mv_3
&& r
->second
== mv_13
&& r
== --multimap_type::iterator(dst
.upper_bound(mv_3
)) && nt
.empty()) )
240 r
= dst
.insert(src
.extract(mv_4
)); // Key type version, unsuccessful
241 if(! (r
== dst
.end()) )
252 template<class VoidAllocator
, boost::container::tree_type_enum tree_type_value
>
253 struct GetAllocatorMap
255 template<class ValueType
>
258 typedef map
< ValueType
260 , std::less
<ValueType
>
261 , typename allocator_traits
<VoidAllocator
>
262 ::template portable_rebind_alloc
< std::pair
<const ValueType
, ValueType
> >::type
263 , typename
boost::container::tree_assoc_options
264 < boost::container::tree_type
<tree_type_value
>
268 typedef multimap
< ValueType
270 , std::less
<ValueType
>
271 , typename allocator_traits
<VoidAllocator
>
272 ::template portable_rebind_alloc
< std::pair
<const ValueType
, ValueType
> >::type
273 , typename
boost::container::tree_assoc_options
274 < boost::container::tree_type
<tree_type_value
>
280 template<class VoidAllocator
, boost::container::tree_type_enum tree_type_value
>
281 int test_map_variants()
283 typedef typename GetAllocatorMap
<VoidAllocator
, tree_type_value
>::template apply
<int>::map_type MyMap
;
284 typedef typename GetAllocatorMap
<VoidAllocator
, tree_type_value
>::template apply
<test::movable_int
>::map_type MyMoveMap
;
285 typedef typename GetAllocatorMap
<VoidAllocator
, tree_type_value
>::template apply
<test::movable_and_copyable_int
>::map_type MyCopyMoveMap
;
286 typedef typename GetAllocatorMap
<VoidAllocator
, tree_type_value
>::template apply
<test::copyable_int
>::map_type MyCopyMap
;
288 typedef typename GetAllocatorMap
<VoidAllocator
, tree_type_value
>::template apply
<int>::multimap_type MyMultiMap
;
289 typedef typename GetAllocatorMap
<VoidAllocator
, tree_type_value
>::template apply
<test::movable_int
>::multimap_type MyMoveMultiMap
;
290 typedef typename GetAllocatorMap
<VoidAllocator
, tree_type_value
>::template apply
<test::movable_and_copyable_int
>::multimap_type MyCopyMoveMultiMap
;
291 typedef typename GetAllocatorMap
<VoidAllocator
, tree_type_value
>::template apply
<test::copyable_int
>::multimap_type MyCopyMultiMap
;
293 typedef std::map
<int, int> MyStdMap
;
294 typedef std::multimap
<int, int> MyStdMultiMap
;
296 if (0 != test::map_test
<
301 std::cout
<< "Error in map_test<MyBoostMap>" << std::endl
;
305 if (0 != test::map_test
<
310 std::cout
<< "Error in map_test<MyBoostMap>" << std::endl
;
314 if (0 != test::map_test
<
319 std::cout
<< "Error in map_test<MyBoostMap>" << std::endl
;
323 if (0 != test::map_test
<
328 std::cout
<< "Error in map_test<MyBoostMap>" << std::endl
;
335 struct boost_container_map
;
336 struct boost_container_multimap
;
338 namespace boost
{ namespace container
{ namespace test
{
341 struct alloc_propagate_base
<boost_container_map
>
343 template <class T
, class Allocator
>
346 typedef typename
boost::container::allocator_traits
<Allocator
>::
347 template portable_rebind_alloc
<std::pair
<const T
, T
> >::type TypeAllocator
;
348 typedef boost::container::map
<T
, T
, std::less
<T
>, TypeAllocator
> type
;
353 struct alloc_propagate_base
<boost_container_multimap
>
355 template <class T
, class Allocator
>
358 typedef typename
boost::container::allocator_traits
<Allocator
>::
359 template portable_rebind_alloc
<std::pair
<const T
, T
> >::type TypeAllocator
;
360 typedef boost::container::multimap
<T
, T
, std::less
<T
>, TypeAllocator
> type
;
364 void test_merge_from_different_comparison()
367 map
<int, int, std::greater
<int> > map2
;
371 }}} //namespace boost::container::test
375 //Recursive container instantiation
377 map
<recursive_map
, recursive_map
> map_
;
378 multimap
<recursive_multimap
, recursive_multimap
> multimap_
;
380 //Allocator argument container
382 map
<int, int> map_((map
<int, int>::allocator_type()));
383 multimap
<int, int> multimap_((multimap
<int, int>::allocator_type()));
385 //Now test move semantics
387 test_move
<map
<recursive_map
, recursive_map
> >();
388 test_move
<multimap
<recursive_multimap
, recursive_multimap
> >();
391 //Test std::pair value type as tree has workarounds to make old std::pair
392 //implementations movable that can break things
394 boost::container::map
<pair_t
, pair_t
> s
;
395 std::pair
<const pair_t
,pair_t
> p
;
400 ////////////////////////////////////
401 // Testing allocator implementations
402 ////////////////////////////////////
404 if(test_map_variants
< std::allocator
<void>, red_black_tree
>()){
405 std::cerr
<< "test_map_variants< std::allocator<void> > failed" << std::endl
;
408 // boost::container::adaptive_pool
409 if(test_map_variants
< adaptive_pool
<void>, red_black_tree
>()){
410 std::cerr
<< "test_map_variants< adaptive_pool<void> > failed" << std::endl
;
414 ////////////////////////////////////
415 // Tree implementations
416 ////////////////////////////////////
418 if(test_map_variants
< std::allocator
<void>, avl_tree
>()){
419 std::cerr
<< "test_map_variants< std::allocator<void>, avl_tree > failed" << std::endl
;
423 if(test_map_variants
< std::allocator
<void>, scapegoat_tree
>()){
424 std::cerr
<< "test_map_variants< std::allocator<void>, scapegoat_tree > failed" << std::endl
;
428 if(test_map_variants
< std::allocator
<void>, splay_tree
>()){
429 std::cerr
<< "test_map_variants< std::allocator<void>, splay_tree > failed" << std::endl
;
433 ////////////////////////////////////
435 ////////////////////////////////////
436 const test::EmplaceOptions MapOptions
= (test::EmplaceOptions
)(test::EMPLACE_HINT_PAIR
| test::EMPLACE_ASSOC_PAIR
);
437 if(!boost::container::test::test_emplace
<map
<test::EmplaceInt
, test::EmplaceInt
>, MapOptions
>())
439 if(!boost::container::test::test_emplace
<multimap
<test::EmplaceInt
, test::EmplaceInt
>, MapOptions
>())
442 ////////////////////////////////////
443 // Allocator propagation testing
444 ////////////////////////////////////
445 if(!boost::container::test::test_propagate_allocator
<boost_container_map
>())
448 if(!boost::container::test::test_propagate_allocator
<boost_container_multimap
>())
451 if (!boost::container::test::test_map_support_for_initialization_list_for
<map
<int, int> >())
454 if (!boost::container::test::test_map_support_for_initialization_list_for
<multimap
<int, int> >())
457 ////////////////////////////////////
459 ////////////////////////////////////
461 typedef boost::container::map
<int, int> cont_int
;
462 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));
463 boost::intrusive::test::test_iterator_bidirectional
< cont_int
>(a
);
464 if(boost::report_errors() != 0) {
469 typedef boost::container::multimap
<int, int> cont_int
;
470 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));
471 boost::intrusive::test::test_iterator_bidirectional
< cont_int
>(a
);
472 if(boost::report_errors() != 0) {
477 ////////////////////////////////////
478 // Node extraction/insertion testing functions
479 ////////////////////////////////////
480 if(!node_type_test())
483 test::test_merge_from_different_comparison();
485 ////////////////////////////////////
486 // Test optimize_size option
487 ////////////////////////////////////
491 typedef map
< int*, int*, std::less
<int*>, std::allocator
< std::pair
<int const*, int*> >
492 , tree_assoc_options
< optimize_size
<false>, tree_type
<red_black_tree
> >::type
> rbmap_size_optimized_no
;
493 typedef map
< int*, int*, std::less
<int*>, std::allocator
< std::pair
<int const*, int*> >
494 , tree_assoc_options
< optimize_size
<true>, tree_type
<red_black_tree
> >::type
> rbmap_size_optimized_yes
;
495 BOOST_STATIC_ASSERT(sizeof(rbmap_size_optimized_yes
) < sizeof(rbmap_size_optimized_no
));
497 typedef map
< int*, int*, std::less
<int*>, std::allocator
< std::pair
<int const*, int*> >
498 , tree_assoc_options
< optimize_size
<false>, tree_type
<avl_tree
> >::type
> avlmap_size_optimized_no
;
499 typedef map
< int*, int*, std::less
<int*>, std::allocator
< std::pair
<int const*, int*> >
500 , tree_assoc_options
< optimize_size
<true>, tree_type
<avl_tree
> >::type
> avlmap_size_optimized_yes
;
501 BOOST_STATIC_ASSERT(sizeof(avlmap_size_optimized_yes
) < sizeof(avlmap_size_optimized_no
));
505 typedef multimap
< int*, int*, std::less
<int*>, std::allocator
< std::pair
<int const*, int*> >
506 , tree_assoc_options
< optimize_size
<false>, tree_type
<red_black_tree
> >::type
> rbmmap_size_optimized_no
;
507 typedef multimap
< int*, int*, std::less
<int*>, std::allocator
< std::pair
<int const*, int*> >
508 , tree_assoc_options
< optimize_size
<true>, tree_type
<red_black_tree
> >::type
> rbmmap_size_optimized_yes
;
509 BOOST_STATIC_ASSERT(sizeof(rbmmap_size_optimized_yes
) < sizeof(rbmmap_size_optimized_no
));
511 typedef multimap
< int*, int*, std::less
<int*>, std::allocator
< std::pair
<int const*, int*> >
512 , tree_assoc_options
< optimize_size
<false>, tree_type
<avl_tree
> >::type
> avlmmap_size_optimized_no
;
513 typedef multimap
< int*, int*, std::less
<int*>, std::allocator
< std::pair
<int const*, int*> >
514 , tree_assoc_options
< optimize_size
<true>, tree_type
<avl_tree
> >::type
> avlmmap_size_optimized_yes
;
515 BOOST_STATIC_ASSERT(sizeof(avlmmap_size_optimized_yes
) < sizeof(avlmmap_size_optimized_no
));
520 #include <boost/container/detail/config_end.hpp>