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>
15 #include <boost/container/flat_set.hpp>
16 #include <boost/container/stable_vector.hpp>
17 #include <boost/container/small_vector.hpp>
18 #include <boost/container/deque.hpp>
19 #include <boost/container/static_vector.hpp>
20 #include <boost/container/allocator.hpp>
21 #include <boost/container/detail/container_or_allocator_rebind.hpp>
23 #include "print_container.hpp"
24 #include "dummy_test_allocator.hpp"
25 #include "movable_int.hpp"
26 #include "set_test.hpp"
27 #include "propagate_allocator_test.hpp"
28 #include "emplace_test.hpp"
29 #include "container_common_tests.hpp"
30 #include "../../intrusive/test/iterator_test.hpp"
32 using namespace boost::container
;
37 //Explicit instantiation to detect compilation errors
40 template class flat_set
41 < test::movable_and_copyable_int
42 , std::less
<test::movable_and_copyable_int
>
43 , test::simple_allocator
<test::movable_and_copyable_int
>
46 template class flat_set
47 < test::movable_and_copyable_int
48 , std::less
<test::movable_and_copyable_int
>
49 , small_vector
<test::movable_and_copyable_int
, 10, allocator
<test::movable_and_copyable_int
> >
53 template class flat_multiset
54 < test::movable_and_copyable_int
55 , std::less
<test::movable_and_copyable_int
>
56 , stable_vector
<test::movable_and_copyable_int
, test::simple_allocator
<test::movable_and_copyable_int
> >
59 template class flat_multiset
60 < test::movable_and_copyable_int
61 , std::less
<test::movable_and_copyable_int
>
62 , deque
<test::movable_and_copyable_int
, test::simple_allocator
< test::movable_and_copyable_int
> >
65 template class flat_multiset
66 < test::movable_and_copyable_int
67 , std::less
<test::movable_and_copyable_int
>
68 , static_vector
<test::movable_and_copyable_int
, 10 >
71 //As flat container iterators are typedefs for vector::[const_]iterator,
72 //no need to explicit instantiate them
77 #if (__cplusplus > 201103L)
83 template class flat_set
84 < test::movable_and_copyable_int
85 , std::less
<test::movable_and_copyable_int
>
86 , std::vector
<test::movable_and_copyable_int
>
93 //Test recursive structures
94 class recursive_flat_set
97 recursive_flat_set(const recursive_flat_set
&c
)
98 : id_(c
.id_
), flat_set_(c
.flat_set_
)
101 recursive_flat_set
& operator =(const recursive_flat_set
&c
)
104 flat_set_
= c
.flat_set_
;
108 flat_set
<recursive_flat_set
> flat_set_
;
109 flat_set
<recursive_flat_set
>::iterator it_
;
110 flat_set
<recursive_flat_set
>::const_iterator cit_
;
111 flat_set
<recursive_flat_set
>::reverse_iterator rit_
;
112 flat_set
<recursive_flat_set
>::const_reverse_iterator crit_
;
114 friend bool operator< (const recursive_flat_set
&a
, const recursive_flat_set
&b
)
115 { return a
.id_
< b
.id_
; }
119 //Test recursive structures
120 class recursive_flat_multiset
123 recursive_flat_multiset(const recursive_flat_multiset
&c
)
124 : id_(c
.id_
), flat_multiset_(c
.flat_multiset_
)
127 recursive_flat_multiset
& operator =(const recursive_flat_multiset
&c
)
130 flat_multiset_
= c
.flat_multiset_
;
134 flat_multiset
<recursive_flat_multiset
> flat_multiset_
;
135 flat_multiset
<recursive_flat_multiset
>::iterator it_
;
136 flat_multiset
<recursive_flat_multiset
>::const_iterator cit_
;
137 flat_multiset
<recursive_flat_multiset
>::reverse_iterator rit_
;
138 flat_multiset
<recursive_flat_multiset
>::const_reverse_iterator crit_
;
140 friend bool operator< (const recursive_flat_multiset
&a
, const recursive_flat_multiset
&b
)
141 { return a
.id_
< b
.id_
; }
148 //Now test move semantics
150 C
move_ctor(boost::move(original
));
152 move_assign
= boost::move(move_ctor
);
153 move_assign
.swap(original
);
157 namespace container
{
160 bool flat_tree_ordered_insertion_test()
162 using namespace boost::container
;
163 const std::size_t NumElements
= 100;
165 //Ordered insertion multiset
167 std::multiset
<int> int_mset
;
168 for(std::size_t i
= 0; i
!= NumElements
; ++i
){
169 int_mset
.insert(static_cast<int>(i
));
171 //Construction insertion
172 flat_multiset
<int> fmset(ordered_range
, int_mset
.begin(), int_mset
.end());
173 if(!CheckEqualContainers(int_mset
, fmset
))
175 //Insertion when empty
177 fmset
.insert(ordered_range
, int_mset
.begin(), int_mset
.end());
178 if(!CheckEqualContainers(int_mset
, fmset
))
181 fmset
.insert(ordered_range
, int_mset
.begin(), int_mset
.end());
182 std::multiset
<int> int_mset2(int_mset
);
183 int_mset2
.insert(int_mset
.begin(), int_mset
.end());
184 if(!CheckEqualContainers(int_mset2
, fmset
))
187 fmset
.insert(ordered_range
, int_mset2
.begin(), int_mset2
.end());
188 std::multiset
<int> int_mset4(int_mset2
);
189 int_mset4
.insert(int_mset2
.begin(), int_mset2
.end());
190 if(!CheckEqualContainers(int_mset4
, fmset
))
192 //Re-re-insertion of even
193 std::multiset
<int> int_even_mset
;
194 for(std::size_t i
= 0; i
< NumElements
; i
+=2){
195 int_mset
.insert(static_cast<int>(i
));
197 fmset
.insert(ordered_range
, int_even_mset
.begin(), int_even_mset
.end());
198 int_mset4
.insert(int_even_mset
.begin(), int_even_mset
.end());
199 if(!CheckEqualContainers(int_mset4
, fmset
))
202 //Re-re-insertion using in-place merge
203 fmset
.reserve(fmset
.size() + int_mset2
.size());
204 fmset
.insert(ordered_range
, int_mset2
.begin(), int_mset2
.end());
205 std::multiset
<int> int_mset5(int_mset2
);
206 int_mset4
.insert(int_mset5
.begin(), int_mset5
.end());
207 if(!CheckEqualContainers(int_mset4
, fmset
))
209 //Re-re-insertion of even
210 std::multiset
<int> int_even_mset2
;
211 for(std::size_t i
= 0; i
< NumElements
; i
+=2){
212 int_even_mset2
.insert(static_cast<int>(i
));
214 fmset
.reserve(fmset
.size() + int_even_mset2
.size());
215 fmset
.insert(ordered_range
, int_even_mset2
.begin(), int_even_mset2
.end());
216 int_mset4
.insert(int_even_mset2
.begin(), int_even_mset2
.end());
217 if(!CheckEqualContainers(int_mset4
, fmset
))
221 //Ordered insertion set
223 std::set
<int> int_set
;
224 for(std::size_t i
= 0; i
!= NumElements
; ++i
){
225 int_set
.insert(static_cast<int>(i
));
227 //Construction insertion
228 flat_set
<int> fset(ordered_unique_range
, int_set
.begin(), int_set
.end());
229 if(!CheckEqualContainers(int_set
, fset
))
231 //Insertion when empty
233 fset
.insert(ordered_unique_range
, int_set
.begin(), int_set
.end());
234 if(!CheckEqualContainers(int_set
, fset
))
237 fset
.insert(ordered_unique_range
, int_set
.begin(), int_set
.end());
238 std::set
<int> int_set2(int_set
);
239 int_set2
.insert(int_set
.begin(), int_set
.end());
240 if(!CheckEqualContainers(int_set2
, fset
))
243 fset
.insert(ordered_unique_range
, int_set2
.begin(), int_set2
.end());
244 std::set
<int> int_set4(int_set2
);
245 int_set4
.insert(int_set2
.begin(), int_set2
.end());
246 if(!CheckEqualContainers(int_set4
, fset
))
248 //Re-re-insertion of even
249 std::set
<int> int_even_set
;
250 for(std::size_t i
= 0; i
< NumElements
; i
+=2){
251 int_even_set
.insert(static_cast<int>(i
));
253 fset
.insert(ordered_unique_range
, int_even_set
.begin(), int_even_set
.end());
254 int_set4
.insert(int_even_set
.begin(), int_even_set
.end());
255 if(!CheckEqualContainers(int_set4
, fset
))
257 //Partial Re-re-insertion of even
258 int_even_set
.clear();
259 for(std::size_t i
= 0; i
< NumElements
; i
+=4){
260 int_even_set
.insert(static_cast<int>(i
));
265 fset
.insert(ordered_unique_range
, int_even_set
.begin(), int_even_set
.end());
266 int_set4
.insert(int_even_set
.begin(), int_even_set
.end());
267 if(!CheckEqualContainers(int_set4
, fset
))
269 for(std::size_t i
= 2; i
< NumElements
; i
+=4){
270 int_even_set
.insert(static_cast<int>(i
));
272 //insert 0,2,4,6,8,10,12...
273 fset
.insert(ordered_unique_range
, int_even_set
.begin(), int_even_set
.end());
274 int_set4
.insert(int_even_set
.begin(), int_even_set
.end());
275 if(!CheckEqualContainers(int_set4
, fset
))
277 int_even_set
.clear();
278 for(std::size_t i
= 0; i
< NumElements
; i
+=8){
279 int_even_set
.insert(static_cast<int>(i
));
284 fset
.insert(ordered_unique_range
, int_even_set
.begin(), int_even_set
.end());
285 int_set4
.insert(int_even_set
.begin(), int_even_set
.end());
286 if(!CheckEqualContainers(int_set4
, fset
))
288 for(std::size_t i
= 0; i
< NumElements
; i
+=2){
289 int_even_set
.insert(static_cast<int>(i
));
291 //insert 0,2,4,6,8,10,12...
292 fset
.insert(ordered_unique_range
, int_even_set
.begin(), int_even_set
.end());
293 int_set4
.insert(int_even_set
.begin(), int_even_set
.end());
294 if(!CheckEqualContainers(int_set4
, fset
))
298 int_even_set
.clear();
299 for(std::size_t i
= 0; i
< NumElements
; i
+=8){
300 int_even_set
.insert(static_cast<int>(i
));
301 int_even_set
.insert(static_cast<int>(i
+2));
303 int_even_set
.insert(static_cast<int>(NumElements
-2));
307 fset
.insert(ordered_unique_range
, int_even_set
.begin(), int_even_set
.end());
308 int_set4
.insert(int_even_set
.begin(), int_even_set
.end());
309 if(!CheckEqualContainers(int_set4
, fset
))
311 for(std::size_t i
= 0; i
< NumElements
; i
+=2){
312 int_even_set
.insert(static_cast<int>(i
));
314 //insert 0,2,4,6,8,10,12...
315 fset
.insert(ordered_unique_range
, int_even_set
.begin(), int_even_set
.end());
316 int_set4
.insert(int_even_set
.begin(), int_even_set
.end());
317 if(!CheckEqualContainers(int_set4
, fset
))
324 template< class RandomIt
>
325 void random_shuffle( RandomIt first
, RandomIt last
)
327 typedef typename
boost::container::iterator_traits
<RandomIt
>::difference_type difference_type
;
328 difference_type n
= last
- first
;
329 for (difference_type i
= n
-1; i
> 0; --i
) {
330 difference_type j
= std::rand() % (i
+1);
332 boost::adl_move_swap(first
[i
], first
[j
]);
337 bool flat_tree_extract_adopt_test()
339 using namespace boost::container
;
340 const std::size_t NumElements
= 100;
344 //Construction insertion
347 for(std::size_t i
= 0; i
!= NumElements
; ++i
){
348 fset
.insert(static_cast<int>(i
));
351 flat_set
<int> fset_copy(fset
);
352 flat_set
<int>::sequence_type
seq(fset
.extract_sequence());
355 if(!CheckEqualContainers(seq
, fset_copy
))
358 seq
.insert(seq
.end(), fset_copy
.begin(), fset_copy
.end());
359 boost::container::test::random_shuffle(seq
.begin(), seq
.end());
360 fset
.adopt_sequence(boost::move(seq
));
361 if(!CheckEqualContainers(fset
, fset_copy
))
365 //extract/adopt set, ordered_unique_range
367 //Construction insertion
370 for(std::size_t i
= 0; i
!= NumElements
; ++i
){
371 fset
.insert(static_cast<int>(i
));
374 flat_set
<int> fset_copy(fset
);
375 flat_set
<int>::sequence_type
seq(fset
.extract_sequence());
378 if(!CheckEqualContainers(seq
, fset_copy
))
381 fset
.adopt_sequence(ordered_unique_range
, boost::move(seq
));
382 if(!CheckEqualContainers(fset
, fset_copy
))
386 //extract/adopt multiset
388 //Construction insertion
389 flat_multiset
<int> fmset
;
391 for(std::size_t i
= 0; i
!= NumElements
; ++i
){
392 fmset
.insert(static_cast<int>(i
));
393 fmset
.insert(static_cast<int>(i
));
396 flat_multiset
<int> fmset_copy(fmset
);
397 flat_multiset
<int>::sequence_type
seq(fmset
.extract_sequence());
400 if(!CheckEqualContainers(seq
, fmset_copy
))
403 boost::container::test::random_shuffle(seq
.begin(), seq
.end());
404 fmset
.adopt_sequence(boost::move(seq
));
405 if(!CheckEqualContainers(fmset
, fmset_copy
))
409 //extract/adopt multiset, ordered_range
411 //Construction insertion
412 flat_multiset
<int> fmset
;
414 for(std::size_t i
= 0; i
!= NumElements
; ++i
){
415 fmset
.insert(static_cast<int>(i
));
416 fmset
.insert(static_cast<int>(i
));
419 flat_multiset
<int> fmset_copy(fmset
);
420 flat_multiset
<int>::sequence_type
seq(fmset
.extract_sequence());
423 if(!CheckEqualContainers(seq
, fmset_copy
))
426 fmset
.adopt_sequence(ordered_range
, boost::move(seq
));
427 if(!CheckEqualContainers(fmset
, fmset_copy
))
436 template<class VoidAllocatorOrContainer
>
437 struct GetSetContainer
439 template<class ValueType
>
442 typedef flat_set
< ValueType
443 , std::less
<ValueType
>
444 , typename
boost::container::container_detail::container_or_allocator_rebind
<VoidAllocatorOrContainer
, ValueType
>::type
447 typedef flat_multiset
< ValueType
448 , std::less
<ValueType
>
449 , typename
boost::container::container_detail::container_or_allocator_rebind
<VoidAllocatorOrContainer
, ValueType
>::type
454 template<class VoidAllocator
>
455 int test_set_variants()
457 typedef typename GetSetContainer
<VoidAllocator
>::template apply
<int>::set_type MySet
;
458 typedef typename GetSetContainer
<VoidAllocator
>::template apply
<test::movable_int
>::set_type MyMoveSet
;
459 typedef typename GetSetContainer
<VoidAllocator
>::template apply
<test::movable_and_copyable_int
>::set_type MyCopyMoveSet
;
460 typedef typename GetSetContainer
<VoidAllocator
>::template apply
<test::copyable_int
>::set_type MyCopySet
;
462 typedef typename GetSetContainer
<VoidAllocator
>::template apply
<int>::multiset_type MyMultiSet
;
463 typedef typename GetSetContainer
<VoidAllocator
>::template apply
<test::movable_int
>::multiset_type MyMoveMultiSet
;
464 typedef typename GetSetContainer
<VoidAllocator
>::template apply
<test::movable_and_copyable_int
>::multiset_type MyCopyMoveMultiSet
;
465 typedef typename GetSetContainer
<VoidAllocator
>::template apply
<test::copyable_int
>::multiset_type MyCopyMultiSet
;
467 typedef std::set
<int> MyStdSet
;
468 typedef std::multiset
<int> MyStdMultiSet
;
470 if (0 != test::set_test
<
475 std::cout
<< "Error in set_test<MyBoostSet>" << std::endl
;
479 if (0 != test::set_test
<
484 std::cout
<< "Error in set_test<MyBoostSet>" << std::endl
;
488 if (0 != test::set_test
<
493 std::cout
<< "Error in set_test<MyBoostSet>" << std::endl
;
497 if (0 != test::set_test
<
502 std::cout
<< "Error in set_test<MyBoostSet>" << std::endl
;
510 template<typename FlatSetType
>
511 bool test_support_for_initialization_list_for()
513 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
514 const std::initializer_list
<int> il
517 const FlatSetType
expected(il
.begin(), il
.end());
519 const FlatSetType sil
= il
;
523 const FlatSetType
sil_ordered(ordered_unique_range
, il
);
524 if(sil_ordered
!= expected
)
527 FlatSetType sil_assign
= {99};
529 if(sil_assign
!= expected
)
543 struct boost_container_flat_set
;
544 struct boost_container_flat_multiset
;
547 namespace container
{
551 struct alloc_propagate_base
<boost_container_flat_set
>
553 template <class T
, class Allocator
>
556 typedef boost::container::flat_set
<T
, std::less
<T
>, Allocator
> type
;
561 struct alloc_propagate_base
<boost_container_flat_multiset
>
563 template <class T
, class Allocator
>
566 typedef boost::container::flat_multiset
<T
, std::less
<T
>, Allocator
> type
;
570 }}} //boost::container::test
574 using namespace boost::container::test
;
576 //Allocator argument container
578 flat_set
<int> set_((flat_set
<int>::allocator_type()));
579 flat_multiset
<int> multiset_((flat_multiset
<int>::allocator_type()));
581 //Now test move semantics
583 test_move
<flat_set
<recursive_flat_set
> >();
584 test_move
<flat_multiset
<recursive_flat_multiset
> >();
586 //Now test nth/index_of
589 flat_multiset
<int> mset
;
597 if(!boost::container::test::test_nth_index_of(set
))
599 if(!boost::container::test::test_nth_index_of(mset
))
603 ////////////////////////////////////
604 // Ordered insertion test
605 ////////////////////////////////////
606 if(!flat_tree_ordered_insertion_test()){
610 ////////////////////////////////////
611 // Extract/Adopt test
612 ////////////////////////////////////
613 if(!flat_tree_extract_adopt_test()){
617 if (!boost::container::test::instantiate_constructors
<flat_set
<int>, flat_multiset
<int> >())
620 ////////////////////////////////////
621 // Testing allocator implementations
622 ////////////////////////////////////
624 if(test_set_variants
< std::allocator
<void> >()){
625 std::cerr
<< "test_set_variants< std::allocator<void> > failed" << std::endl
;
628 // boost::container::allocator
629 if(test_set_variants
< allocator
<void> >()){
630 std::cerr
<< "test_set_variants< allocator<void> > failed" << std::endl
;
634 ////////////////////////////////////
636 ////////////////////////////////////
637 const test::EmplaceOptions SetOptions
= (test::EmplaceOptions
)(test::EMPLACE_HINT
| test::EMPLACE_ASSOC
);
639 if(!boost::container::test::test_emplace
<flat_set
<test::EmplaceInt
>, SetOptions
>())
641 if(!boost::container::test::test_emplace
<flat_multiset
<test::EmplaceInt
>, SetOptions
>())
644 if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for
<flat_set
<int> >())
647 if (!boost::container::test::test_set_methods_with_initializer_list_as_argument_for
<flat_multiset
<int> >())
650 ////////////////////////////////////
651 // Allocator propagation testing
652 ////////////////////////////////////
653 if(!boost::container::test::test_propagate_allocator
<boost_container_flat_set
>())
656 if(!boost::container::test::test_propagate_allocator
<boost_container_flat_multiset
>())
659 ////////////////////////////////////
661 ////////////////////////////////////
663 typedef boost::container::flat_set
<int> cont_int
;
664 cont_int a
; a
.insert(0); a
.insert(1); a
.insert(2);
665 boost::intrusive::test::test_iterator_random
< cont_int
>(a
);
666 if(boost::report_errors() != 0) {
671 typedef boost::container::flat_multiset
<int> cont_int
;
672 cont_int a
; a
.insert(0); a
.insert(1); a
.insert(2);
673 boost::intrusive::test::test_iterator_random
< cont_int
>(a
);
674 if(boost::report_errors() != 0) {
682 #include <boost/container/detail/config_end.hpp>