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>
12 #include <boost/container/set.hpp>
13 #include <boost/container/adaptive_pool.hpp>
15 #include "print_container.hpp"
16 #include "movable_int.hpp"
17 #include "dummy_test_allocator.hpp"
18 #include "set_test.hpp"
19 #include "propagate_allocator_test.hpp"
20 #include "emplace_test.hpp"
21 #include "../../intrusive/test/iterator_test.hpp"
23 using namespace boost::container
;
28 //Explicit instantiation to detect compilation errors
32 < test::movable_and_copyable_int
33 , std::less
<test::movable_and_copyable_int
>
34 , test::simple_allocator
<test::movable_and_copyable_int
>
38 < test::movable_and_copyable_int
39 , std::less
<test::movable_and_copyable_int
>
40 , new_allocator
<test::movable_and_copyable_int
>
44 template class multiset
45 < test::movable_and_copyable_int
46 , std::less
<test::movable_and_copyable_int
>
47 , test::simple_allocator
<test::movable_and_copyable_int
>
50 template class multiset
51 < test::movable_and_copyable_int
52 , std::less
<test::movable_and_copyable_int
>
53 , adaptive_pool
<test::movable_and_copyable_int
>
58 //Test recursive structures
62 recursive_set
& operator=(const recursive_set
&x
)
63 { id_
= x
.id_
; set_
= x
.set_
; return *this; }
66 set
<recursive_set
> set_
;
67 set
<recursive_set
>::iterator it_
;
68 set
<recursive_set
>::const_iterator cit_
;
69 set
<recursive_set
>::reverse_iterator rit_
;
70 set
<recursive_set
>::const_reverse_iterator crit_
;
72 friend bool operator< (const recursive_set
&a
, const recursive_set
&b
)
73 { return a
.id_
< b
.id_
; }
76 //Test recursive structures
77 class recursive_multiset
80 recursive_multiset
& operator=(const recursive_multiset
&x
)
81 { id_
= x
.id_
; multiset_
= x
.multiset_
; return *this; }
84 multiset
<recursive_multiset
> multiset_
;
85 multiset
<recursive_multiset
>::iterator it_
;
86 multiset
<recursive_multiset
>::const_iterator cit_
;
87 multiset
<recursive_multiset
>::reverse_iterator rit_
;
88 multiset
<recursive_multiset
>::const_reverse_iterator crit_
;
90 friend bool operator< (const recursive_multiset
&a
, const recursive_multiset
&b
)
91 { return a
.id_
< b
.id_
; }
97 //Now test move semantics
100 C
move_ctor(boost::move(original
));
102 move_assign
.emplace();
103 move_assign
= boost::move(move_ctor
);
104 move_assign
.swap(original
);
107 bool node_type_test()
109 using namespace boost::container
;
111 typedef set
<test::movable_int
> set_type
;
114 test::movable_int
mv_1(1), mv_2(2), mv_3(3);
115 src
.emplace(boost::move(mv_1
));
116 src
.emplace(boost::move(mv_2
));
117 src
.emplace(boost::move(mv_3
));
124 test::movable_int
mv_3(3);
125 dst
.emplace(boost::move(mv_3
));
131 const test::movable_int
mv_1(1);
132 const test::movable_int
mv_2(2);
133 const test::movable_int
mv_3(3);
134 const test::movable_int
mv_33(33);
135 set_type::insert_return_type r
;
137 r
= dst
.insert(src
.extract(mv_33
)); // Key version, try to insert empty node
138 if(! (r
.position
== dst
.end() && r
.inserted
== false && r
.node
.empty()) )
140 r
= dst
.insert(src
.extract(src
.find(mv_1
))); // Iterator version, successful
141 if(! (r
.position
== dst
.find(mv_1
) && r
.inserted
== true && r
.node
.empty()) )
143 r
= dst
.insert(dst
.begin(), src
.extract(mv_2
)); // Key type version, successful
144 if(! (r
.position
== dst
.find(mv_2
) && r
.inserted
== true && r
.node
.empty()) )
146 r
= dst
.insert(src
.extract(mv_3
)); // Key type version, unsuccessful
152 if(! (r
.position
== dst
.find(mv_3
) && r
.inserted
== false && r
.node
.value() == mv_3
) )
157 typedef multiset
<test::movable_int
> multiset_type
;
160 test::movable_int
mv_1(1), mv_2(2), mv_3(3), mv_3bis(3);
161 src
.emplace(boost::move(mv_1
));
162 src
.emplace(boost::move(mv_2
));
163 src
.emplace(boost::move(mv_3
));
164 src
.emplace_hint(src
.begin(), boost::move(mv_3bis
));
171 test::movable_int
mv_3(3);
172 dst
.emplace(boost::move(mv_3
));
178 const test::movable_int
mv_1(1);
179 const test::movable_int
mv_2(2);
180 const test::movable_int
mv_3(3);
181 const test::movable_int
mv_4(4);
182 multiset_type::iterator r
;
184 multiset_type::node_type
nt(src
.extract(mv_3
));
185 r
= dst
.insert(dst
.begin(), boost::move(nt
));
186 if(! (*r
== mv_3
&& 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
== mv_1
&& nt
.empty()) )
194 nt
= src
.extract(mv_2
);
195 r
= dst
.insert(boost::move(nt
)); // Key type version, successful
196 if(! (*r
== mv_2
&& nt
.empty()) )
199 r
= dst
.insert(src
.extract(mv_3
)); // Key type version, successful
200 if(! (*r
== mv_3
&& r
== --multiset_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 struct boost_container_set
;
216 struct boost_container_multiset
;
219 namespace container
{
223 struct alloc_propagate_base
<boost_container_set
>
225 template <class T
, class Allocator
>
228 typedef boost::container::set
<T
, std::less
<T
>, Allocator
> type
;
233 struct alloc_propagate_base
<boost_container_multiset
>
235 template <class T
, class Allocator
>
238 typedef boost::container::multiset
<T
, std::less
<T
>, Allocator
> type
;
242 }}} //boost::container::test
244 template<class VoidAllocator
, boost::container::tree_type_enum tree_type_value
>
245 struct GetAllocatorSet
247 template<class ValueType
>
250 typedef set
< ValueType
251 , std::less
<ValueType
>
252 , typename allocator_traits
<VoidAllocator
>
253 ::template portable_rebind_alloc
<ValueType
>::type
254 , typename
boost::container::tree_assoc_options
255 < boost::container::tree_type
<tree_type_value
>
259 typedef multiset
< ValueType
260 , std::less
<ValueType
>
261 , typename allocator_traits
<VoidAllocator
>
262 ::template portable_rebind_alloc
<ValueType
>::type
263 , typename
boost::container::tree_assoc_options
264 < boost::container::tree_type
<tree_type_value
>
270 template<class VoidAllocator
, boost::container::tree_type_enum tree_type_value
>
271 int test_set_variants()
273 typedef typename GetAllocatorSet
<VoidAllocator
, tree_type_value
>::template apply
<int>::set_type MySet
;
274 typedef typename GetAllocatorSet
<VoidAllocator
, tree_type_value
>::template apply
<test::movable_int
>::set_type MyMoveSet
;
275 typedef typename GetAllocatorSet
<VoidAllocator
, tree_type_value
>::template apply
<test::copyable_int
>::set_type MyCopySet
;
277 typedef typename GetAllocatorSet
<VoidAllocator
, tree_type_value
>::template apply
<int>::multiset_type MyMultiSet
;
278 typedef typename GetAllocatorSet
<VoidAllocator
, tree_type_value
>::template apply
<test::movable_int
>::multiset_type MyMoveMultiSet
;
279 typedef typename GetAllocatorSet
<VoidAllocator
, tree_type_value
>::template apply
<test::copyable_int
>::multiset_type MyCopyMultiSet
;
281 typedef std::set
<int> MyStdSet
;
282 typedef std::multiset
<int> MyStdMultiSet
;
284 if (0 != test::set_test
<
289 std::cout
<< "Error in set_test<MyBoostSet>" << std::endl
;
293 if (0 != test::set_test
<
298 std::cout
<< "Error in set_test<MyBoostSet>" << std::endl
;
302 if (0 != test::set_test
<
307 std::cout
<< "Error in set_test<MyBoostSet>" << std::endl
;
314 void test_merge_from_different_comparison()
317 set
<int, std::greater
<int> > set2
;
323 //Recursive container instantiation
325 set
<recursive_set
> set_
;
326 multiset
<recursive_multiset
> multiset_
;
328 //Allocator argument container
330 set
<int> set_((set
<int>::allocator_type()));
331 multiset
<int> multiset_((multiset
<int>::allocator_type()));
333 //Now test move semantics
335 test_move
<set
<recursive_set
> >();
336 test_move
<multiset
<recursive_multiset
> >();
338 //Test std::pair value type as tree has workarounds to make old std::pair
339 //implementations movable that can break things
341 boost::container::set
<std::pair
<int,int> > s
;
342 std::pair
<int,int> p(0, 0);
347 if (!boost::container::test::instantiate_constructors
<set
<int>, multiset
<int> >())
350 test_merge_from_different_comparison();
352 ////////////////////////////////////
353 // Testing allocator implementations
354 ////////////////////////////////////
356 if(test_set_variants
< std::allocator
<void>, red_black_tree
>()){
357 std::cerr
<< "test_set_variants< std::allocator<void> > failed" << std::endl
;
360 // boost::container::adaptive_pool
361 if(test_set_variants
< adaptive_pool
<void>, red_black_tree
>()){
362 std::cerr
<< "test_set_variants< adaptive_pool<void> > failed" << std::endl
;
366 ////////////////////////////////////
367 // Tree implementations
368 ////////////////////////////////////
370 if(test_set_variants
< std::allocator
<void>, avl_tree
>()){
371 std::cerr
<< "test_set_variants< std::allocator<void>, avl_tree > failed" << std::endl
;
375 if(test_set_variants
< std::allocator
<void>, scapegoat_tree
>()){
376 std::cerr
<< "test_set_variants< std::allocator<void>, scapegoat_tree > failed" << std::endl
;
380 if(test_set_variants
< std::allocator
<void>, splay_tree
>()){
381 std::cerr
<< "test_set_variants< std::allocator<void>, splay_tree > failed" << std::endl
;
385 ////////////////////////////////////
387 ////////////////////////////////////
388 const test::EmplaceOptions SetOptions
= (test::EmplaceOptions
)(test::EMPLACE_HINT
| test::EMPLACE_ASSOC
);
389 if(!boost::container::test::test_emplace
<set
<test::EmplaceInt
>, SetOptions
>())
391 if(!boost::container::test::test_emplace
<multiset
<test::EmplaceInt
>, SetOptions
>())
394 ////////////////////////////////////
395 // Allocator propagation testing
396 ////////////////////////////////////
397 if(!boost::container::test::test_propagate_allocator
<boost_container_set
>())
400 if(!boost::container::test::test_propagate_allocator
<boost_container_multiset
>())
403 if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for
<set
<int> >())
406 if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for
<multiset
<int> >())
409 ////////////////////////////////////
410 // Test optimize_size option
411 ////////////////////////////////////
415 typedef set
< int*, std::less
<int*>, std::allocator
<int*>
416 , tree_assoc_options
< optimize_size
<false>, tree_type
<red_black_tree
> >::type
> rbset_size_optimized_no
;
418 typedef set
< int*, std::less
<int*>, std::allocator
<int*>
419 , tree_assoc_options
< optimize_size
<true>, tree_type
<avl_tree
> >::type
> avlset_size_optimized_yes
;
423 typedef multiset
< int*, std::less
<int*>, std::allocator
<int*>
424 , tree_assoc_options
< optimize_size
<true>, tree_type
<red_black_tree
> >::type
> rbmset_size_optimized_yes
;
426 typedef multiset
< int*, std::less
<int*>, std::allocator
<int*>
427 , tree_assoc_options
< optimize_size
<false>, tree_type
<avl_tree
> >::type
> avlmset_size_optimized_no
;
429 BOOST_STATIC_ASSERT(sizeof(rbmset_size_optimized_yes
) < sizeof(rbset_size_optimized_no
));
430 BOOST_STATIC_ASSERT(sizeof(avlset_size_optimized_yes
) < sizeof(avlmset_size_optimized_no
));
432 ////////////////////////////////////
434 ////////////////////////////////////
436 typedef boost::container::set
<int> cont_int
;
437 cont_int a
; a
.insert(0); a
.insert(1); a
.insert(2);
438 boost::intrusive::test::test_iterator_bidirectional
< cont_int
>(a
);
439 if(boost::report_errors() != 0) {
444 typedef boost::container::multiset
<int> cont_int
;
445 cont_int a
; a
.insert(0); a
.insert(1); a
.insert(2);
446 boost::intrusive::test::test_iterator_bidirectional
< cont_int
>(a
);
447 if(boost::report_errors() != 0) {
452 ////////////////////////////////////
453 // Node extraction/insertion testing functions
454 ////////////////////////////////////
455 if(!node_type_test())
461 #include <boost/container/detail/config_end.hpp>