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>
12 #include <boost/container/flat_map.hpp>
13 #include <boost/container/allocator.hpp>
14 #include <boost/container/detail/flat_tree.hpp>
15 #include <boost/container/stable_vector.hpp>
16 #include <boost/container/small_vector.hpp>
17 #include <boost/container/deque.hpp>
18 #include <boost/container/static_vector.hpp>
19 #include <boost/container/detail/container_or_allocator_rebind.hpp>
21 #include "print_container.hpp"
22 #include "dummy_test_allocator.hpp"
23 #include "movable_int.hpp"
24 #include "map_test.hpp"
25 #include "propagate_allocator_test.hpp"
26 #include "container_common_tests.hpp"
27 #include "emplace_test.hpp"
28 #include "../../intrusive/test/iterator_test.hpp"
33 using namespace boost::container
;
38 //Explicit instantiation to detect compilation errors
41 typedef std::pair
<test::movable_and_copyable_int
, test::movable_and_copyable_int
> test_pair_t
;
43 template class flat_map
44 < test::movable_and_copyable_int
45 , test::movable_and_copyable_int
46 , std::less
<test::movable_and_copyable_int
>
47 , test::simple_allocator
< test_pair_t
>
50 template class flat_map
51 < test::movable_and_copyable_int
52 , test::movable_and_copyable_int
53 , std::less
<test::movable_and_copyable_int
>
54 , small_vector
< test_pair_t
, 10, std::allocator
< test_pair_t
> >
58 template class flat_multimap
59 < test::movable_and_copyable_int
60 , test::movable_and_copyable_int
61 , std::less
<test::movable_and_copyable_int
>
62 , stable_vector
< test_pair_t
, allocator
< test_pair_t
> >
65 template class flat_multimap
66 < test::movable_and_copyable_int
67 , test::movable_and_copyable_int
68 , std::less
<test::movable_and_copyable_int
>
69 , deque
<test_pair_t
, test::simple_allocator
< test_pair_t
> >
72 template class flat_multimap
73 < test::movable_and_copyable_int
74 , test::movable_and_copyable_int
75 , std::less
<test::movable_and_copyable_int
>
76 , static_vector
<test_pair_t
, 10 >
79 //As flat container iterators are typedefs for vector::[const_]iterator,
80 //no need to explicit instantiate them
84 #if (__cplusplus > 201103L)
90 template class flat_map
91 < test::movable_and_copyable_int
92 , test::movable_and_copyable_int
93 , std::less
<test::movable_and_copyable_int
>
94 , std::vector
<test_pair_t
>
101 class recursive_flat_map
104 recursive_flat_map(const recursive_flat_map
&c
)
105 : id_(c
.id_
), map_(c
.map_
)
108 recursive_flat_map
& operator =(const recursive_flat_map
&c
)
116 flat_map
<recursive_flat_map
, recursive_flat_map
> map_
;
117 flat_map
<recursive_flat_map
, recursive_flat_map
>::iterator it_
;
118 flat_map
<recursive_flat_map
, recursive_flat_map
>::const_iterator cit_
;
119 flat_map
<recursive_flat_map
, recursive_flat_map
>::reverse_iterator rit_
;
120 flat_map
<recursive_flat_map
, recursive_flat_map
>::const_reverse_iterator crit_
;
122 friend bool operator< (const recursive_flat_map
&a
, const recursive_flat_map
&b
)
123 { return a
.id_
< b
.id_
; }
127 class recursive_flat_multimap
130 recursive_flat_multimap(const recursive_flat_multimap
&c
)
131 : id_(c
.id_
), map_(c
.map_
)
134 recursive_flat_multimap
& operator =(const recursive_flat_multimap
&c
)
141 flat_multimap
<recursive_flat_multimap
, recursive_flat_multimap
> map_
;
142 flat_multimap
<recursive_flat_multimap
, recursive_flat_multimap
>::iterator it_
;
143 flat_multimap
<recursive_flat_multimap
, recursive_flat_multimap
>::const_iterator cit_
;
144 flat_multimap
<recursive_flat_multimap
, recursive_flat_multimap
>::reverse_iterator rit_
;
145 flat_multimap
<recursive_flat_multimap
, recursive_flat_multimap
>::const_reverse_iterator crit_
;
147 friend bool operator< (const recursive_flat_multimap
&a
, const recursive_flat_multimap
&b
)
148 { return a
.id_
< b
.id_
; }
154 //Now test move semantics
156 C
move_ctor(boost::move(original
));
158 move_assign
= boost::move(move_ctor
);
159 move_assign
.swap(original
);
164 namespace container
{
167 bool flat_tree_ordered_insertion_test()
169 using namespace boost::container
;
170 const std::size_t NumElements
= 100;
172 //Ordered insertion multimap
174 std::multimap
<int, int> int_mmap
;
175 for(std::size_t i
= 0; i
!= NumElements
; ++i
){
176 int_mmap
.insert(std::multimap
<int, int>::value_type(static_cast<int>(i
), static_cast<int>(i
)));
178 //Construction insertion
179 flat_multimap
<int, int> fmmap(ordered_range
, int_mmap
.begin(), int_mmap
.end());
180 if(!CheckEqualContainers(int_mmap
, fmmap
))
182 //Insertion when empty
184 fmmap
.insert(ordered_range
, int_mmap
.begin(), int_mmap
.end());
185 if(!CheckEqualContainers(int_mmap
, fmmap
))
188 fmmap
.insert(ordered_range
, int_mmap
.begin(), int_mmap
.end());
189 std::multimap
<int, int> int_mmap2(int_mmap
);
190 int_mmap2
.insert(int_mmap
.begin(), int_mmap
.end());
191 if(!CheckEqualContainers(int_mmap2
, fmmap
))
194 fmmap
.insert(ordered_range
, int_mmap2
.begin(), int_mmap2
.end());
195 std::multimap
<int, int> int_mmap4(int_mmap2
);
196 int_mmap4
.insert(int_mmap2
.begin(), int_mmap2
.end());
197 if(!CheckEqualContainers(int_mmap4
, fmmap
))
199 //Re-re-insertion of even
200 std::multimap
<int, int> int_even_mmap
;
201 for(std::size_t i
= 0; i
< NumElements
; i
+=2){
202 int_mmap
.insert(std::multimap
<int, int>::value_type(static_cast<int>(i
), static_cast<int>(i
)));
204 fmmap
.insert(ordered_range
, int_even_mmap
.begin(), int_even_mmap
.end());
205 int_mmap4
.insert(int_even_mmap
.begin(), int_even_mmap
.end());
206 if(!CheckEqualContainers(int_mmap4
, fmmap
))
210 //Ordered insertion map
212 std::map
<int, int> int_map
;
213 for(std::size_t i
= 0; i
!= NumElements
; ++i
){
214 int_map
.insert(std::map
<int, int>::value_type(static_cast<int>(i
), static_cast<int>(i
)));
216 //Construction insertion
217 flat_map
<int, int> fmap(ordered_unique_range
, int_map
.begin(), int_map
.end());
218 if(!CheckEqualContainers(int_map
, fmap
))
220 //Insertion when empty
222 fmap
.insert(ordered_unique_range
, int_map
.begin(), int_map
.end());
223 if(!CheckEqualContainers(int_map
, fmap
))
226 fmap
.insert(ordered_unique_range
, int_map
.begin(), int_map
.end());
227 std::map
<int, int> int_map2(int_map
);
228 int_map2
.insert(int_map
.begin(), int_map
.end());
229 if(!CheckEqualContainers(int_map2
, fmap
))
232 fmap
.insert(ordered_unique_range
, int_map2
.begin(), int_map2
.end());
233 std::map
<int, int> int_map4(int_map2
);
234 int_map4
.insert(int_map2
.begin(), int_map2
.end());
235 if(!CheckEqualContainers(int_map4
, fmap
))
237 //Re-re-insertion of even
238 std::map
<int, int> int_even_map
;
239 for(std::size_t i
= 0; i
< NumElements
; i
+=2){
240 int_map
.insert(std::map
<int, int>::value_type(static_cast<int>(i
), static_cast<int>(i
)));
242 fmap
.insert(ordered_unique_range
, int_even_map
.begin(), int_even_map
.end());
243 int_map4
.insert(int_even_map
.begin(), int_even_map
.end());
244 if(!CheckEqualContainers(int_map4
, fmap
))
251 template< class RandomIt
>
252 void random_shuffle( RandomIt first
, RandomIt last
)
254 typedef typename
boost::container::iterator_traits
<RandomIt
>::difference_type difference_type
;
255 difference_type n
= last
- first
;
256 for (difference_type i
= n
-1; i
> 0; --i
) {
257 difference_type j
= std::rand() % (i
+1);
259 boost::adl_move_swap(first
[i
], first
[j
]);
264 bool flat_tree_extract_adopt_test()
266 using namespace boost::container
;
267 const std::size_t NumElements
= 100;
271 //Construction insertion
272 flat_map
<int, int> fmap
;
274 for(std::size_t i
= 0; i
!= NumElements
; ++i
){
275 fmap
.emplace(static_cast<int>(i
), -static_cast<int>(i
));
278 flat_map
<int, int> fmap_copy(fmap
);
279 flat_map
<int, int>::sequence_type
seq(fmap
.extract_sequence());
282 if(!CheckEqualContainers(seq
, fmap_copy
))
285 seq
.insert(seq
.end(), fmap_copy
.begin(), fmap_copy
.end());
286 boost::container::test::random_shuffle(seq
.begin(), seq
.end());
287 fmap
.adopt_sequence(boost::move(seq
));
288 if(!CheckEqualContainers(fmap
, fmap_copy
))
292 //extract/adopt map, ordered_unique_range
294 //Construction insertion
295 flat_map
<int, int> fmap
;
297 for(std::size_t i
= 0; i
!= NumElements
; ++i
){
298 fmap
.emplace(static_cast<int>(i
), -static_cast<int>(i
));
301 flat_map
<int, int> fmap_copy(fmap
);
302 flat_map
<int, int>::sequence_type
seq(fmap
.extract_sequence());
305 if(!CheckEqualContainers(seq
, fmap_copy
))
308 fmap
.adopt_sequence(ordered_unique_range
, boost::move(seq
));
309 if(!CheckEqualContainers(fmap
, fmap_copy
))
313 //extract/adopt multimap
315 //Construction insertion
316 flat_multimap
<int, int> fmmap
;
318 for(std::size_t i
= 0; i
!= NumElements
; ++i
){
319 fmmap
.emplace(static_cast<int>(i
), -static_cast<int>(i
));
320 fmmap
.emplace(static_cast<int>(i
), -static_cast<int>(i
));
323 flat_multimap
<int, int> fmmap_copy(fmmap
);
324 flat_multimap
<int, int>::sequence_type
seq(fmmap
.extract_sequence());
327 if(!CheckEqualContainers(seq
, fmmap_copy
))
330 boost::container::test::random_shuffle(seq
.begin(), seq
.end());
331 fmmap
.adopt_sequence(boost::move(seq
));
332 if(!CheckEqualContainers(fmmap
, fmmap_copy
))
336 //extract/adopt multimap, ordered_range
338 //Construction insertion
339 flat_multimap
<int, int> fmmap
;
341 for(std::size_t i
= 0; i
!= NumElements
; ++i
){
342 fmmap
.emplace(static_cast<int>(i
), -static_cast<int>(i
));
343 fmmap
.emplace(static_cast<int>(i
), -static_cast<int>(i
));
346 flat_multimap
<int, int> fmmap_copy(fmmap
);
347 flat_multimap
<int, int>::sequence_type
seq(fmmap
.extract_sequence());
350 if(!CheckEqualContainers(seq
, fmmap_copy
))
353 fmmap
.adopt_sequence(ordered_range
, boost::move(seq
));
354 if(!CheckEqualContainers(fmmap
, fmmap_copy
))
363 template<class VoidAllocatorOrContainer
>
364 struct GetMapContainer
366 template<class ValueType
>
369 typedef std::pair
<ValueType
, ValueType
> type_t
;
370 typedef flat_map
< ValueType
372 , std::less
<ValueType
>
373 , typename
boost::container::container_detail::container_or_allocator_rebind
<VoidAllocatorOrContainer
, type_t
>::type
376 typedef flat_multimap
< ValueType
378 , std::less
<ValueType
>
379 , typename
boost::container::container_detail::container_or_allocator_rebind
<VoidAllocatorOrContainer
, type_t
>::type
384 struct boost_container_flat_map
;
385 struct boost_container_flat_multimap
;
387 namespace boost
{ namespace container
{ namespace test
{
390 struct alloc_propagate_base
<boost_container_flat_map
>
392 template <class T
, class Allocator
>
395 typedef typename
boost::container::allocator_traits
<Allocator
>::
396 template portable_rebind_alloc
<std::pair
<T
, T
> >::type TypeAllocator
;
397 typedef boost::container::flat_map
<T
, T
, std::less
<T
>, TypeAllocator
> type
;
402 struct alloc_propagate_base
<boost_container_flat_multimap
>
404 template <class T
, class Allocator
>
407 typedef typename
boost::container::allocator_traits
<Allocator
>::
408 template portable_rebind_alloc
<std::pair
<T
, T
> >::type TypeAllocator
;
409 typedef boost::container::flat_multimap
<T
, T
, std::less
<T
>, TypeAllocator
> type
;
413 template <class Key
, class T
, class Compare
, class Allocator
>
414 struct get_real_stored_allocator
<flat_map
<Key
, T
, Compare
, Allocator
> >
416 typedef typename flat_map
<Key
, T
, Compare
, Allocator
>::impl_stored_allocator_type type
;
419 template <class Key
, class T
, class Compare
, class Allocator
>
420 struct get_real_stored_allocator
<flat_multimap
<Key
, T
, Compare
, Allocator
> >
422 typedef typename flat_multimap
<Key
, T
, Compare
, Allocator
>::impl_stored_allocator_type type
;
425 }}} //namespace boost::container::test
427 template<class VoidAllocatorOrContainer
>
428 int test_map_variants()
430 typedef typename GetMapContainer
<VoidAllocatorOrContainer
>::template apply
<int>::map_type MyMap
;
431 typedef typename GetMapContainer
<VoidAllocatorOrContainer
>::template apply
<test::movable_int
>::map_type MyMoveMap
;
432 typedef typename GetMapContainer
<VoidAllocatorOrContainer
>::template apply
<test::movable_and_copyable_int
>::map_type MyCopyMoveMap
;
433 typedef typename GetMapContainer
<VoidAllocatorOrContainer
>::template apply
<test::copyable_int
>::map_type MyCopyMap
;
435 typedef typename GetMapContainer
<VoidAllocatorOrContainer
>::template apply
<int>::multimap_type MyMultiMap
;
436 typedef typename GetMapContainer
<VoidAllocatorOrContainer
>::template apply
<test::movable_int
>::multimap_type MyMoveMultiMap
;
437 typedef typename GetMapContainer
<VoidAllocatorOrContainer
>::template apply
<test::movable_and_copyable_int
>::multimap_type MyCopyMoveMultiMap
;
438 typedef typename GetMapContainer
<VoidAllocatorOrContainer
>::template apply
<test::copyable_int
>::multimap_type MyCopyMultiMap
;
440 typedef std::map
<int, int> MyStdMap
;
441 typedef std::multimap
<int, int> MyStdMultiMap
;
443 if (0 != test::map_test
<
448 std::cout
<< "Error in map_test<MyBoostMap>" << std::endl
;
452 if (0 != test::map_test
<
457 std::cout
<< "Error in map_test<MyBoostMap>" << std::endl
;
461 if (0 != test::map_test
<
466 std::cout
<< "Error in map_test<MyBoostMap>" << std::endl
;
470 if (0 != test::map_test
<
475 std::cout
<< "Error in map_test<MyBoostMap>" << std::endl
;
484 using namespace boost::container::test
;
486 //Allocator argument container
488 flat_map
<int, int> map_((flat_map
<int, int>::allocator_type()));
489 flat_multimap
<int, int> multimap_((flat_multimap
<int, int>::allocator_type()));
491 //Now test move semantics
493 test_move
<flat_map
<recursive_flat_map
, recursive_flat_map
> >();
494 test_move
<flat_multimap
<recursive_flat_multimap
, recursive_flat_multimap
> >();
496 //Now test nth/index_of
498 flat_map
<int, int> map
;
499 flat_multimap
<int, int> mmap
;
501 map
.insert(std::pair
<int, int>(0, 0));
502 map
.insert(std::pair
<int, int>(1, 0));
503 map
.insert(std::pair
<int, int>(2, 0));
504 mmap
.insert(std::pair
<int, int>(0, 0));
505 mmap
.insert(std::pair
<int, int>(1, 0));
506 mmap
.insert(std::pair
<int, int>(2, 0));
507 if(!boost::container::test::test_nth_index_of(map
))
509 if(!boost::container::test::test_nth_index_of(mmap
))
513 ////////////////////////////////////
514 // Ordered insertion test
515 ////////////////////////////////////
516 if(!flat_tree_ordered_insertion_test()){
520 ////////////////////////////////////
521 // Extract/Adopt test
522 ////////////////////////////////////
523 if(!flat_tree_extract_adopt_test()){
527 if (!boost::container::test::instantiate_constructors
<flat_map
<int, int>, flat_multimap
<int, int> >())
530 ////////////////////////////////////
531 // Testing allocator implementations
532 ////////////////////////////////////
534 if(test_map_variants
< std::allocator
<void> >()){
535 std::cerr
<< "test_map_variants< std::allocator<void> > failed" << std::endl
;
538 // boost::container::allocator
539 if(test_map_variants
< allocator
<void> >()){
540 std::cerr
<< "test_map_variants< allocator<void> > failed" << std::endl
;
544 if(!boost::container::test::test_map_support_for_initialization_list_for
<flat_map
<int, int> >())
547 if (!boost::container::test::test_map_support_for_initialization_list_for
<flat_multimap
<int, int> >())
550 ////////////////////////////////////
552 ////////////////////////////////////
553 const test::EmplaceOptions MapOptions
= (test::EmplaceOptions
)(test::EMPLACE_HINT_PAIR
| test::EMPLACE_ASSOC_PAIR
);
555 if(!boost::container::test::test_emplace
<flat_map
<test::EmplaceInt
, test::EmplaceInt
>, MapOptions
>())
557 if(!boost::container::test::test_emplace
<flat_multimap
<test::EmplaceInt
, test::EmplaceInt
>, MapOptions
>())
560 ////////////////////////////////////
561 // Allocator propagation testing
562 ////////////////////////////////////
563 if(!boost::container::test::test_propagate_allocator
<boost_container_flat_map
>())
566 if(!boost::container::test::test_propagate_allocator
<boost_container_flat_multimap
>())
569 ////////////////////////////////////
571 ////////////////////////////////////
573 typedef boost::container::flat_map
<int, int> cont_int
;
574 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));
575 boost::intrusive::test::test_iterator_random
< cont_int
>(a
);
576 if(boost::report_errors() != 0) {
581 typedef boost::container::flat_multimap
<int, int> cont_int
;
582 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));
583 boost::intrusive::test::test_iterator_random
< cont_int
>(a
);
584 if(boost::report_errors() != 0) {
592 #include <boost/container/detail/config_end.hpp>