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 //////////////////////////////////////////////////////////////////////////////
11 #include <boost/container/detail/config_begin.hpp>
13 #include <boost/container/flat_set.hpp>
14 #include <boost/container/allocator.hpp>
16 #include "print_container.hpp"
17 #include "dummy_test_allocator.hpp"
18 #include "movable_int.hpp"
19 #include "set_test.hpp"
20 #include "propagate_allocator_test.hpp"
21 #include "emplace_test.hpp"
22 #include "container_common_tests.hpp"
24 #include <boost/container/detail/flat_tree.hpp>
25 #include "../../intrusive/test/iterator_test.hpp"
27 using namespace boost::container
;
32 //Explicit instantiation to detect compilation errors
35 template class flat_set
36 < test::movable_and_copyable_int
37 , std::less
<test::movable_and_copyable_int
>
38 , test::simple_allocator
<test::movable_and_copyable_int
>
41 template class flat_set
42 < test::movable_and_copyable_int
43 , std::less
<test::movable_and_copyable_int
>
44 , allocator
<test::movable_and_copyable_int
>
48 template class flat_multiset
49 < test::movable_and_copyable_int
50 , std::less
<test::movable_and_copyable_int
>
51 , test::simple_allocator
<test::movable_and_copyable_int
>
54 template class flat_multiset
55 < test::movable_and_copyable_int
56 , std::less
<test::movable_and_copyable_int
>
57 , allocator
<test::movable_and_copyable_int
>
60 namespace container_detail
{
62 //Instantiate base class as previous instantiations don't instantiate inherited members
63 template class flat_tree
64 < test::movable_and_copyable_int
65 , identity
<test::movable_and_copyable_int
>
66 , std::less
<test::movable_and_copyable_int
>
67 , test::simple_allocator
<test::movable_and_copyable_int
>
70 template class flat_tree
71 < test::movable_and_copyable_int
72 , identity
<test::movable_and_copyable_int
>
73 , std::less
<test::movable_and_copyable_int
>
74 , allocator
<test::movable_and_copyable_int
>
77 } //container_detail {
79 //As flat container iterators are typedefs for vector::[const_]iterator,
80 //no need to explicit instantiate them
84 //Test recursive structures
85 class recursive_flat_set
88 recursive_flat_set(const recursive_flat_set
&c
)
89 : id_(c
.id_
), flat_set_(c
.flat_set_
)
92 recursive_flat_set
& operator =(const recursive_flat_set
&c
)
95 flat_set_
= c
.flat_set_
;
99 flat_set
<recursive_flat_set
> flat_set_
;
100 flat_set
<recursive_flat_set
>::iterator it_
;
101 flat_set
<recursive_flat_set
>::const_iterator cit_
;
102 flat_set
<recursive_flat_set
>::reverse_iterator rit_
;
103 flat_set
<recursive_flat_set
>::const_reverse_iterator crit_
;
105 friend bool operator< (const recursive_flat_set
&a
, const recursive_flat_set
&b
)
106 { return a
.id_
< b
.id_
; }
110 //Test recursive structures
111 class recursive_flat_multiset
114 recursive_flat_multiset(const recursive_flat_multiset
&c
)
115 : id_(c
.id_
), flat_multiset_(c
.flat_multiset_
)
118 recursive_flat_multiset
& operator =(const recursive_flat_multiset
&c
)
121 flat_multiset_
= c
.flat_multiset_
;
125 flat_multiset
<recursive_flat_multiset
> flat_multiset_
;
126 flat_multiset
<recursive_flat_multiset
>::iterator it_
;
127 flat_multiset
<recursive_flat_multiset
>::const_iterator cit_
;
128 flat_multiset
<recursive_flat_multiset
>::reverse_iterator rit_
;
129 flat_multiset
<recursive_flat_multiset
>::const_reverse_iterator crit_
;
131 friend bool operator< (const recursive_flat_multiset
&a
, const recursive_flat_multiset
&b
)
132 { return a
.id_
< b
.id_
; }
139 //Now test move semantics
141 C
move_ctor(boost::move(original
));
143 move_assign
= boost::move(move_ctor
);
144 move_assign
.swap(original
);
148 namespace container
{
151 bool flat_tree_ordered_insertion_test()
153 using namespace boost::container
;
154 const std::size_t NumElements
= 100;
156 //Ordered insertion multiset
158 std::multiset
<int> int_mset
;
159 for(std::size_t i
= 0; i
!= NumElements
; ++i
){
160 int_mset
.insert(static_cast<int>(i
));
162 //Construction insertion
163 flat_multiset
<int> fmset(ordered_range
, int_mset
.begin(), int_mset
.end());
164 if(!CheckEqualContainers(int_mset
, fmset
))
166 //Insertion when empty
168 fmset
.insert(ordered_range
, int_mset
.begin(), int_mset
.end());
169 if(!CheckEqualContainers(int_mset
, fmset
))
172 fmset
.insert(ordered_range
, int_mset
.begin(), int_mset
.end());
173 std::multiset
<int> int_mset2(int_mset
);
174 int_mset2
.insert(int_mset
.begin(), int_mset
.end());
175 if(!CheckEqualContainers(int_mset2
, fmset
))
178 fmset
.insert(ordered_range
, int_mset2
.begin(), int_mset2
.end());
179 std::multiset
<int> int_mset4(int_mset2
);
180 int_mset4
.insert(int_mset2
.begin(), int_mset2
.end());
181 if(!CheckEqualContainers(int_mset4
, fmset
))
183 //Re-re-insertion of even
184 std::multiset
<int> int_even_mset
;
185 for(std::size_t i
= 0; i
< NumElements
; i
+=2){
186 int_mset
.insert(static_cast<int>(i
));
188 fmset
.insert(ordered_range
, int_even_mset
.begin(), int_even_mset
.end());
189 int_mset4
.insert(int_even_mset
.begin(), int_even_mset
.end());
190 if(!CheckEqualContainers(int_mset4
, fmset
))
193 //Re-re-insertion using in-place merge
194 fmset
.reserve(fmset
.size() + int_mset2
.size());
195 fmset
.insert(ordered_range
, int_mset2
.begin(), int_mset2
.end());
196 std::multiset
<int> int_mset5(int_mset2
);
197 int_mset4
.insert(int_mset5
.begin(), int_mset5
.end());
198 if(!CheckEqualContainers(int_mset4
, fmset
))
200 //Re-re-insertion of even
201 std::multiset
<int> int_even_mset2
;
202 for(std::size_t i
= 0; i
< NumElements
; i
+=2){
203 int_even_mset2
.insert(static_cast<int>(i
));
205 fmset
.reserve(fmset
.size() + int_even_mset2
.size());
206 fmset
.insert(ordered_range
, int_even_mset2
.begin(), int_even_mset2
.end());
207 int_mset4
.insert(int_even_mset2
.begin(), int_even_mset2
.end());
208 if(!CheckEqualContainers(int_mset4
, fmset
))
212 //Ordered insertion set
214 std::set
<int> int_set
;
215 for(std::size_t i
= 0; i
!= NumElements
; ++i
){
216 int_set
.insert(static_cast<int>(i
));
218 //Construction insertion
219 flat_set
<int> fset(ordered_unique_range
, int_set
.begin(), int_set
.end());
220 if(!CheckEqualContainers(int_set
, fset
))
222 //Insertion when empty
224 fset
.insert(ordered_unique_range
, int_set
.begin(), int_set
.end());
225 if(!CheckEqualContainers(int_set
, fset
))
228 fset
.insert(ordered_unique_range
, int_set
.begin(), int_set
.end());
229 std::set
<int> int_set2(int_set
);
230 int_set2
.insert(int_set
.begin(), int_set
.end());
231 if(!CheckEqualContainers(int_set2
, fset
))
234 fset
.insert(ordered_unique_range
, int_set2
.begin(), int_set2
.end());
235 std::set
<int> int_set4(int_set2
);
236 int_set4
.insert(int_set2
.begin(), int_set2
.end());
237 if(!CheckEqualContainers(int_set4
, fset
))
239 //Re-re-insertion of even
240 std::set
<int> int_even_set
;
241 for(std::size_t i
= 0; i
< NumElements
; i
+=2){
242 int_even_set
.insert(static_cast<int>(i
));
244 fset
.insert(ordered_unique_range
, int_even_set
.begin(), int_even_set
.end());
245 int_set4
.insert(int_even_set
.begin(), int_even_set
.end());
246 if(!CheckEqualContainers(int_set4
, fset
))
248 //Partial Re-re-insertion of even
249 int_even_set
.clear();
250 for(std::size_t i
= 0; i
< NumElements
; i
+=4){
251 int_even_set
.insert(static_cast<int>(i
));
256 fset
.insert(ordered_unique_range
, int_even_set
.begin(), int_even_set
.end());
257 int_set4
.insert(int_even_set
.begin(), int_even_set
.end());
258 if(!CheckEqualContainers(int_set4
, fset
))
260 for(std::size_t i
= 2; i
< NumElements
; i
+=4){
261 int_even_set
.insert(static_cast<int>(i
));
263 //insert 0,2,4,6,8,10,12...
264 fset
.insert(ordered_unique_range
, int_even_set
.begin(), int_even_set
.end());
265 int_set4
.insert(int_even_set
.begin(), int_even_set
.end());
266 if(!CheckEqualContainers(int_set4
, fset
))
268 int_even_set
.clear();
269 for(std::size_t i
= 0; i
< NumElements
; i
+=8){
270 int_even_set
.insert(static_cast<int>(i
));
275 fset
.insert(ordered_unique_range
, int_even_set
.begin(), int_even_set
.end());
276 int_set4
.insert(int_even_set
.begin(), int_even_set
.end());
277 if(!CheckEqualContainers(int_set4
, fset
))
279 for(std::size_t i
= 0; i
< NumElements
; i
+=2){
280 int_even_set
.insert(static_cast<int>(i
));
282 //insert 0,2,4,6,8,10,12...
283 fset
.insert(ordered_unique_range
, int_even_set
.begin(), int_even_set
.end());
284 int_set4
.insert(int_even_set
.begin(), int_even_set
.end());
285 if(!CheckEqualContainers(int_set4
, fset
))
289 int_even_set
.clear();
290 for(std::size_t i
= 0; i
< NumElements
; i
+=8){
291 int_even_set
.insert(static_cast<int>(i
));
292 int_even_set
.insert(static_cast<int>(i
+2));
294 int_even_set
.insert(static_cast<int>(NumElements
-2));
298 fset
.insert(ordered_unique_range
, int_even_set
.begin(), int_even_set
.end());
299 int_set4
.insert(int_even_set
.begin(), int_even_set
.end());
300 if(!CheckEqualContainers(int_set4
, fset
))
302 for(std::size_t i
= 0; i
< NumElements
; i
+=2){
303 int_even_set
.insert(static_cast<int>(i
));
305 //insert 0,2,4,6,8,10,12...
306 fset
.insert(ordered_unique_range
, int_even_set
.begin(), int_even_set
.end());
307 int_set4
.insert(int_even_set
.begin(), int_even_set
.end());
308 if(!CheckEqualContainers(int_set4
, fset
))
318 template<class VoidAllocator
>
319 struct GetAllocatorSet
321 template<class ValueType
>
324 typedef flat_set
< ValueType
325 , std::less
<ValueType
>
326 , typename allocator_traits
<VoidAllocator
>
327 ::template portable_rebind_alloc
<ValueType
>::type
330 typedef flat_multiset
< ValueType
331 , std::less
<ValueType
>
332 , typename allocator_traits
<VoidAllocator
>
333 ::template portable_rebind_alloc
<ValueType
>::type
338 template<class VoidAllocator
>
339 int test_set_variants()
341 typedef typename GetAllocatorSet
<VoidAllocator
>::template apply
<int>::set_type MySet
;
342 typedef typename GetAllocatorSet
<VoidAllocator
>::template apply
<test::movable_int
>::set_type MyMoveSet
;
343 typedef typename GetAllocatorSet
<VoidAllocator
>::template apply
<test::movable_and_copyable_int
>::set_type MyCopyMoveSet
;
344 typedef typename GetAllocatorSet
<VoidAllocator
>::template apply
<test::copyable_int
>::set_type MyCopySet
;
346 typedef typename GetAllocatorSet
<VoidAllocator
>::template apply
<int>::multiset_type MyMultiSet
;
347 typedef typename GetAllocatorSet
<VoidAllocator
>::template apply
<test::movable_int
>::multiset_type MyMoveMultiSet
;
348 typedef typename GetAllocatorSet
<VoidAllocator
>::template apply
<test::movable_and_copyable_int
>::multiset_type MyCopyMoveMultiSet
;
349 typedef typename GetAllocatorSet
<VoidAllocator
>::template apply
<test::copyable_int
>::multiset_type MyCopyMultiSet
;
351 typedef std::set
<int> MyStdSet
;
352 typedef std::multiset
<int> MyStdMultiSet
;
354 if (0 != test::set_test
<
359 std::cout
<< "Error in set_test<MyBoostSet>" << std::endl
;
363 if (0 != test::set_test
<
368 std::cout
<< "Error in set_test<MyBoostSet>" << std::endl
;
372 if (0 != test::set_test
<
377 std::cout
<< "Error in set_test<MyBoostSet>" << std::endl
;
381 if (0 != test::set_test
<
386 std::cout
<< "Error in set_test<MyBoostSet>" << std::endl
;
394 template<typename FlatSetType
>
395 bool test_support_for_initialization_list_for()
397 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
398 const std::initializer_list
<int> il
401 const FlatSetType
expected(il
.begin(), il
.end());
403 const FlatSetType sil
= il
;
407 const FlatSetType
sil_ordered(ordered_unique_range
, il
);
408 if(sil_ordered
!= expected
)
411 FlatSetType sil_assign
= {99};
413 if(sil_assign
!= expected
)
427 struct boost_container_flat_set
;
428 struct boost_container_flat_multiset
;
431 namespace container
{
435 struct alloc_propagate_base
<boost_container_flat_set
>
437 template <class T
, class Allocator
>
440 typedef boost::container::flat_set
<T
, std::less
<T
>, Allocator
> type
;
445 struct alloc_propagate_base
<boost_container_flat_multiset
>
447 template <class T
, class Allocator
>
450 typedef boost::container::flat_multiset
<T
, std::less
<T
>, Allocator
> type
;
454 }}} //boost::container::test
458 using namespace boost::container::test
;
460 //Allocator argument container
462 flat_set
<int> set_((flat_set
<int>::allocator_type()));
463 flat_multiset
<int> multiset_((flat_multiset
<int>::allocator_type()));
465 //Now test move semantics
467 test_move
<flat_set
<recursive_flat_set
> >();
468 test_move
<flat_multiset
<recursive_flat_multiset
> >();
470 //Now test nth/index_of
473 flat_multiset
<int> mset
;
481 if(!boost::container::test::test_nth_index_of(set
))
483 if(!boost::container::test::test_nth_index_of(mset
))
487 ////////////////////////////////////
488 // Ordered insertion test
489 ////////////////////////////////////
490 if(!flat_tree_ordered_insertion_test()){
494 ////////////////////////////////////
495 // Testing allocator implementations
496 ////////////////////////////////////
498 if(test_set_variants
< std::allocator
<void> >()){
499 std::cerr
<< "test_set_variants< std::allocator<void> > failed" << std::endl
;
502 // boost::container::allocator
503 if(test_set_variants
< allocator
<void> >()){
504 std::cerr
<< "test_set_variants< allocator<void> > failed" << std::endl
;
508 ////////////////////////////////////
510 ////////////////////////////////////
511 const test::EmplaceOptions SetOptions
= (test::EmplaceOptions
)(test::EMPLACE_HINT
| test::EMPLACE_ASSOC
);
513 if(!boost::container::test::test_emplace
<flat_set
<test::EmplaceInt
>, SetOptions
>())
515 if(!boost::container::test::test_emplace
<flat_multiset
<test::EmplaceInt
>, SetOptions
>())
518 if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for
<flat_set
<int> >())
521 if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for
<flat_multiset
<int> >())
524 ////////////////////////////////////
525 // Allocator propagation testing
526 ////////////////////////////////////
527 if(!boost::container::test::test_propagate_allocator
<boost_container_flat_set
>())
530 if(!boost::container::test::test_propagate_allocator
<boost_container_flat_multiset
>())
533 ////////////////////////////////////
535 ////////////////////////////////////
537 typedef boost::container::flat_set
<int> cont_int
;
538 cont_int a
; a
.insert(0); a
.insert(1); a
.insert(2);
539 boost::intrusive::test::test_iterator_random
< cont_int
>(a
);
540 if(boost::report_errors() != 0) {
545 typedef boost::container::flat_multiset
<int> cont_int
;
546 cont_int a
; a
.insert(0); a
.insert(1); a
.insert(2);
547 boost::intrusive::test::test_iterator_random
< cont_int
>(a
);
548 if(boost::report_errors() != 0) {
556 #include <boost/container/detail/config_end.hpp>