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 , adaptive_pool
< pair_t
>
48 template class multimap
49 < test::movable_and_copyable_int
50 , test::movable_and_copyable_int
51 , std::less
<test::movable_and_copyable_int
>
52 , std::allocator
< pair_t
>
59 recursive_map
& operator=(const recursive_map
&x
)
60 { id_
= x
.id_
; map_
= x
.map_
; return *this; }
63 map
<recursive_map
, recursive_map
> map_
;
64 map
<recursive_map
, recursive_map
>::iterator it_
;
65 map
<recursive_map
, recursive_map
>::const_iterator cit_
;
66 map
<recursive_map
, recursive_map
>::reverse_iterator rit_
;
67 map
<recursive_map
, recursive_map
>::const_reverse_iterator crit_
;
69 friend bool operator< (const recursive_map
&a
, const recursive_map
&b
)
70 { return a
.id_
< b
.id_
; }
73 class recursive_multimap
76 recursive_multimap
& operator=(const recursive_multimap
&x
)
77 { id_
= x
.id_
; multimap_
= x
.multimap_
; return *this; }
80 multimap
<recursive_multimap
, recursive_multimap
> multimap_
;
81 multimap
<recursive_multimap
, recursive_multimap
>::iterator it_
;
82 multimap
<recursive_multimap
, recursive_multimap
>::const_iterator cit_
;
83 multimap
<recursive_multimap
, recursive_multimap
>::reverse_iterator rit_
;
84 multimap
<recursive_multimap
, recursive_multimap
>::const_reverse_iterator crit_
;
86 friend bool operator< (const recursive_multimap
&a
, const recursive_multimap
&b
)
87 { return a
.id_
< b
.id_
; }
93 //Now test move semantics
96 C
move_ctor(boost::move(original
));
98 move_assign
.emplace();
99 move_assign
= boost::move(move_ctor
);
100 move_assign
.swap(original
);
103 bool node_type_test()
105 using namespace boost::container
;
107 typedef map
<test::movable_int
, test::movable_int
> map_type
;
110 test::movable_int
mv_1(1), mv_2(2), mv_3(3), mv_11(11), mv_12(12), mv_13(13);
111 src
.try_emplace(boost::move(mv_1
), boost::move(mv_11
));
112 src
.try_emplace(boost::move(mv_2
), boost::move(mv_12
));
113 src
.try_emplace(boost::move(mv_3
), boost::move(mv_13
));
120 test::movable_int
mv_3(3), mv_33(33);
121 dst
.try_emplace(boost::move(mv_3
), boost::move(mv_33
));
127 const test::movable_int
mv_1(1);
128 const test::movable_int
mv_2(2);
129 const test::movable_int
mv_3(3);
130 const test::movable_int
mv_33(33);
131 const test::movable_int
mv_13(13);
132 map_type::insert_return_type r
;
134 r
= dst
.insert(src
.extract(mv_33
)); // Key version, try to insert empty node
135 if(! (r
.position
== dst
.end() && r
.inserted
== false && r
.node
.empty()) )
137 r
= dst
.insert(src
.extract(src
.find(mv_1
))); // Iterator version, successful
138 if(! (r
.position
== dst
.find(mv_1
) && r
.inserted
== true && r
.node
.empty()) )
140 r
= dst
.insert(dst
.begin(), src
.extract(mv_2
)); // Key type version, successful
141 if(! (r
.position
== dst
.find(mv_2
) && r
.inserted
== true && r
.node
.empty()) )
143 r
= dst
.insert(src
.extract(mv_3
)); // Key type version, unsuccessful
149 if(! (r
.position
== dst
.find(mv_3
) && r
.inserted
== false && r
.node
.key() == mv_3
&& r
.node
.mapped() == mv_13
) )
154 typedef multimap
<test::movable_int
, test::movable_int
> multimap_type
;
157 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);
158 src
.emplace(boost::move(mv_1
), boost::move(mv_11
));
159 src
.emplace(boost::move(mv_2
), boost::move(mv_12
));
160 src
.emplace(boost::move(mv_3
), boost::move(mv_13
));
161 src
.emplace_hint(src
.begin(), boost::move(mv_3bis
), boost::move(mv_23
));
168 test::movable_int
mv_3(3), mv_33(33);
169 dst
.emplace(boost::move(mv_3
), boost::move(mv_33
));
175 const test::movable_int
mv_1(1);
176 const test::movable_int
mv_2(2);
177 const test::movable_int
mv_3(3);
178 const test::movable_int
mv_4(4);
179 const test::movable_int
mv_33(33);
180 const test::movable_int
mv_13(13);
181 const test::movable_int
mv_23(23);
182 multimap_type::iterator r
;
184 multimap_type::node_type
nt(src
.extract(mv_3
));
185 r
= dst
.insert(dst
.begin(), boost::move(nt
));
186 if(! (r
->first
== mv_3
&& r
->second
== mv_23
&& dst
.find(mv_3
) == r
&& nt
.empty()) )
189 nt
= src
.extract(src
.find(mv_1
));
190 r
= dst
.insert(boost::move(nt
)); // Iterator version, successful
191 if(! (r
->first
== mv_1
&& nt
.empty()) )
194 nt
= src
.extract(mv_2
);
195 r
= dst
.insert(boost::move(nt
)); // Key type version, successful
196 if(! (r
->first
== mv_2
&& nt
.empty()) )
199 r
= dst
.insert(src
.extract(mv_3
)); // Key type version, successful
200 if(! (r
->first
== mv_3
&& r
->second
== mv_13
&& r
== --multimap_type::iterator(dst
.upper_bound(mv_3
)) && nt
.empty()) )
203 r
= dst
.insert(src
.extract(mv_4
)); // Key type version, unsuccessful
204 if(! (r
== dst
.end()) )
215 template<class VoidAllocator
, boost::container::tree_type_enum tree_type_value
>
216 struct GetAllocatorMap
218 template<class ValueType
>
221 typedef map
< ValueType
223 , std::less
<ValueType
>
224 , typename allocator_traits
<VoidAllocator
>
225 ::template portable_rebind_alloc
< std::pair
<const ValueType
, ValueType
> >::type
226 , typename
boost::container::tree_assoc_options
227 < boost::container::tree_type
<tree_type_value
>
231 typedef multimap
< ValueType
233 , std::less
<ValueType
>
234 , typename allocator_traits
<VoidAllocator
>
235 ::template portable_rebind_alloc
< std::pair
<const ValueType
, ValueType
> >::type
236 , typename
boost::container::tree_assoc_options
237 < boost::container::tree_type
<tree_type_value
>
243 template<class VoidAllocator
, boost::container::tree_type_enum tree_type_value
>
244 int test_map_variants()
246 typedef typename GetAllocatorMap
<VoidAllocator
, tree_type_value
>::template apply
<int>::map_type MyMap
;
247 typedef typename GetAllocatorMap
<VoidAllocator
, tree_type_value
>::template apply
<test::movable_int
>::map_type MyMoveMap
;
248 typedef typename GetAllocatorMap
<VoidAllocator
, tree_type_value
>::template apply
<test::copyable_int
>::map_type MyCopyMap
;
250 typedef typename GetAllocatorMap
<VoidAllocator
, tree_type_value
>::template apply
<int>::multimap_type MyMultiMap
;
251 typedef typename GetAllocatorMap
<VoidAllocator
, tree_type_value
>::template apply
<test::movable_int
>::multimap_type MyMoveMultiMap
;
252 typedef typename GetAllocatorMap
<VoidAllocator
, tree_type_value
>::template apply
<test::copyable_int
>::multimap_type MyCopyMultiMap
;
254 typedef std::map
<int, int> MyStdMap
;
255 typedef std::multimap
<int, int> MyStdMultiMap
;
257 if (0 != test::map_test
<
262 std::cout
<< "Error in map_test<MyBoostMap>" << std::endl
;
266 if (0 != test::map_test
<
271 std::cout
<< "Error in map_test<MyBoostMap>" << std::endl
;
275 if (0 != test::map_test
<
280 std::cout
<< "Error in map_test<MyBoostMap>" << std::endl
;
287 struct boost_container_map
;
288 struct boost_container_multimap
;
290 namespace boost
{ namespace container
{ namespace test
{
293 struct alloc_propagate_base
<boost_container_map
>
295 template <class T
, class Allocator
>
298 typedef typename
boost::container::allocator_traits
<Allocator
>::
299 template portable_rebind_alloc
<std::pair
<const T
, T
> >::type TypeAllocator
;
300 typedef boost::container::map
<T
, T
, std::less
<T
>, TypeAllocator
> type
;
305 struct alloc_propagate_base
<boost_container_multimap
>
307 template <class T
, class Allocator
>
310 typedef typename
boost::container::allocator_traits
<Allocator
>::
311 template portable_rebind_alloc
<std::pair
<const T
, T
> >::type TypeAllocator
;
312 typedef boost::container::multimap
<T
, T
, std::less
<T
>, TypeAllocator
> type
;
316 void test_merge_from_different_comparison()
319 map
<int, int, std::greater
<int> > map2
;
323 }}} //namespace boost::container::test
327 //Recursive container instantiation
329 map
<recursive_map
, recursive_map
> map_
;
330 multimap
<recursive_multimap
, recursive_multimap
> multimap_
;
332 //Allocator argument container
334 map
<int, int> map_((map
<int, int>::allocator_type()));
335 multimap
<int, int> multimap_((multimap
<int, int>::allocator_type()));
337 //Now test move semantics
339 test_move
<map
<recursive_map
, recursive_map
> >();
340 test_move
<multimap
<recursive_multimap
, recursive_multimap
> >();
343 //Test std::pair value type as tree has workarounds to make old std::pair
344 //implementations movable that can break things
346 boost::container::map
<pair_t
, pair_t
> s
;
347 std::pair
<const pair_t
,pair_t
> p
;
352 ////////////////////////////////////
353 // Testing allocator implementations
354 ////////////////////////////////////
356 if(test_map_variants
< std::allocator
<void>, red_black_tree
>()){
357 std::cerr
<< "test_map_variants< std::allocator<void> > failed" << std::endl
;
360 // boost::container::adaptive_pool
361 if(test_map_variants
< adaptive_pool
<void>, red_black_tree
>()){
362 std::cerr
<< "test_map_variants< adaptive_pool<void> > failed" << std::endl
;
366 ////////////////////////////////////
367 // Tree implementations
368 ////////////////////////////////////
370 if(test_map_variants
< std::allocator
<void>, avl_tree
>()){
371 std::cerr
<< "test_map_variants< std::allocator<void>, avl_tree > failed" << std::endl
;
375 if(test_map_variants
< std::allocator
<void>, scapegoat_tree
>()){
376 std::cerr
<< "test_map_variants< std::allocator<void>, scapegoat_tree > failed" << std::endl
;
380 if(test_map_variants
< std::allocator
<void>, splay_tree
>()){
381 std::cerr
<< "test_map_variants< std::allocator<void>, splay_tree > failed" << std::endl
;
385 ////////////////////////////////////
387 ////////////////////////////////////
388 const test::EmplaceOptions MapOptions
= (test::EmplaceOptions
)(test::EMPLACE_HINT_PAIR
| test::EMPLACE_ASSOC_PAIR
);
389 if(!boost::container::test::test_emplace
<map
<test::EmplaceInt
, test::EmplaceInt
>, MapOptions
>())
391 if(!boost::container::test::test_emplace
<multimap
<test::EmplaceInt
, test::EmplaceInt
>, MapOptions
>())
394 ////////////////////////////////////
395 // Allocator propagation testing
396 ////////////////////////////////////
397 if(!boost::container::test::test_propagate_allocator
<boost_container_map
>())
400 if(!boost::container::test::test_propagate_allocator
<boost_container_multimap
>())
403 if (!boost::container::test::test_map_support_for_initialization_list_for
<map
<int, int> >())
406 if (!boost::container::test::test_map_support_for_initialization_list_for
<multimap
<int, int> >())
409 ////////////////////////////////////
411 ////////////////////////////////////
413 typedef boost::container::map
<int, int> cont_int
;
414 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));
415 boost::intrusive::test::test_iterator_bidirectional
< cont_int
>(a
);
416 if(boost::report_errors() != 0) {
421 typedef boost::container::multimap
<int, int> cont_int
;
422 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));
423 boost::intrusive::test::test_iterator_bidirectional
< cont_int
>(a
);
424 if(boost::report_errors() != 0) {
429 ////////////////////////////////////
430 // Node extraction/insertion testing functions
431 ////////////////////////////////////
432 if(!node_type_test())
435 if (!boost::container::test::instantiate_constructors
<map
<int, int>, multimap
<int, int> >())
438 test::test_merge_from_different_comparison();
440 ////////////////////////////////////
441 // Test optimize_size option
442 ////////////////////////////////////
446 typedef map
< int*, int*, std::less
<int*>, std::allocator
< std::pair
<int *const, int*> >
447 , tree_assoc_options
< optimize_size
<false>, tree_type
<red_black_tree
> >::type
> rbmap_size_optimized_no
;
449 typedef map
< int*, int*, std::less
<int*>, std::allocator
< std::pair
<int *const, int*> >
450 , tree_assoc_options
< optimize_size
<true>, tree_type
<avl_tree
> >::type
> avlmap_size_optimized_yes
;
454 typedef multimap
< int*, int*, std::less
<int*>, std::allocator
< std::pair
<int *const, int*> >
455 , tree_assoc_options
< optimize_size
<true>, tree_type
<red_black_tree
> >::type
> rbmmap_size_optimized_yes
;
456 typedef multimap
< int*, int*, std::less
<int*>, std::allocator
< std::pair
<int *const, int*> >
457 , tree_assoc_options
< optimize_size
<false>, tree_type
<avl_tree
> >::type
> avlmmap_size_optimized_no
;
459 BOOST_STATIC_ASSERT(sizeof(rbmmap_size_optimized_yes
) < sizeof(rbmap_size_optimized_no
));
460 BOOST_STATIC_ASSERT(sizeof(avlmap_size_optimized_yes
) < sizeof(avlmmap_size_optimized_no
));
465 #include <boost/container/detail/config_end.hpp>