• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //////////////////////////////////////////////////////////////////////////////
2 //
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)
6 //
7 // See http://www.boost.org/libs/container for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 
11 // the tests trigger deprecation warnings when compiled with msvc in C++17 mode
12 #if defined(_MSVC_LANG) && _MSVC_LANG > 201402
13 // warning STL4009: std::allocator<void> is deprecated in C++17
14 # define _SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING
15 #endif
16 
17 #include <memory>
18 #include <iostream>
19 
20 #include <boost/container/vector.hpp>
21 #include <boost/container/allocator.hpp>
22 
23 #include <boost/move/utility_core.hpp>
24 #include "check_equal_containers.hpp"
25 #include "movable_int.hpp"
26 #include "expand_bwd_test_allocator.hpp"
27 #include "expand_bwd_test_template.hpp"
28 #include "dummy_test_allocator.hpp"
29 #include "propagate_allocator_test.hpp"
30 #include "vector_test.hpp"
31 #include "default_init_test.hpp"
32 #include "../../intrusive/test/iterator_test.hpp"
33 
34 using namespace boost::container;
35 
test_expand_bwd()36 int test_expand_bwd()
37 {
38    //Now test all back insertion possibilities
39 
40    //First raw ints
41    typedef test::expand_bwd_test_allocator<int>
42       int_allocator_type;
43    typedef vector<int, int_allocator_type>
44       int_vector;
45    if(!test::test_all_expand_bwd<int_vector>())
46       return 1;
47 
48    //Now user defined copyable int
49    typedef test::expand_bwd_test_allocator<test::copyable_int>
50       copyable_int_allocator_type;
51    typedef vector<test::copyable_int, copyable_int_allocator_type>
52       copyable_int_vector;
53    if(!test::test_all_expand_bwd<copyable_int_vector>())
54       return 1;
55 
56    return 0;
57 }
58 
59 struct X;
60 
61 template<typename T>
62 struct XRef
63 {
XRefXRef64    explicit XRef(T* ptr)  : ptr(ptr) {}
operator T*XRef65    operator T*() const { return ptr; }
66    T* ptr;
67 };
68 
69 struct X
70 {
operator &X71    XRef<X const> operator&() const { return XRef<X const>(this); }
operator &X72    XRef<X>       operator&()       { return XRef<X>(this); }
73 };
74 
75 
test_smart_ref_type()76 bool test_smart_ref_type()
77 {
78    boost::container::vector<X> x(5);
79    return x.empty();
80 }
81 
82 class recursive_vector
83 {
84    public:
recursive_vector(const recursive_vector & x)85    recursive_vector (const recursive_vector &x)
86       : vector_(x.vector_)
87    {}
88 
operator =(const recursive_vector & x)89    recursive_vector & operator=(const recursive_vector &x)
90    {  this->vector_ = x.vector_;   return *this; }
91 
92    int id_;
93    vector<recursive_vector> vector_;
94    vector<recursive_vector>::iterator it_;
95    vector<recursive_vector>::const_iterator cit_;
96    vector<recursive_vector>::reverse_iterator rit_;
97    vector<recursive_vector>::const_reverse_iterator crit_;
98 };
99 
recursive_vector_test()100 void recursive_vector_test()//Test for recursive types
101 {
102    vector<recursive_vector> recursive_vector_vector;
103 }
104 
105 enum Test
106 {
107    zero, one, two, three, four, five, six
108 };
109 
110 template<class VoidAllocator>
111 struct GetAllocatorCont
112 {
113    template<class ValueType>
114    struct apply
115    {
116       typedef vector< ValueType
117                     , typename allocator_traits<VoidAllocator>
118                         ::template portable_rebind_alloc<ValueType>::type
119                     > type;
120    };
121 };
122 
123 template<class VoidAllocator>
test_cont_variants()124 int test_cont_variants()
125 {
126    typedef typename GetAllocatorCont<VoidAllocator>::template apply<int>::type MyCont;
127    typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_int>::type MyMoveCont;
128    typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::movable_and_copyable_int>::type MyCopyMoveCont;
129    typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::copyable_int>::type MyCopyCont;
130 
131    if(test::vector_test<MyCont>())
132       return 1;
133    if(test::vector_test<MyMoveCont>())
134       return 1;
135    if(test::vector_test<MyCopyMoveCont>())
136       return 1;
137    if(test::vector_test<MyCopyCont>())
138       return 1;
139 
140    return 0;
141 }
142 
143 struct boost_container_vector;
144 
145 namespace boost { namespace container {   namespace test {
146 
147 template<>
148 struct alloc_propagate_base<boost_container_vector>
149 {
150    template <class T, class Allocator>
151    struct apply
152    {
153       typedef boost::container::vector<T, Allocator> type;
154    };
155 };
156 
157 }}}   //namespace boost::container::test
158 
159 template<typename T>
160 class check_dealloc_allocator : public std::allocator<T>
161 {
162    public:
163    bool allocate_zero_called_;
164    bool deallocate_called_without_allocate_;
165 
check_dealloc_allocator()166    check_dealloc_allocator()
167       : std::allocator<T>()
168       , allocate_zero_called_(false)
169       , deallocate_called_without_allocate_(false)
170    {}
171 
allocate(std::size_t n)172    T* allocate(std::size_t n)
173    {
174       if (n == 0) {
175          allocate_zero_called_ = true;
176       }
177       return std::allocator<T>::allocate(n);
178    }
179 
deallocate(T * p,std::size_t n)180    void deallocate(T* p, std::size_t n)
181    {
182       if (n == 0 && !allocate_zero_called_) {
183          deallocate_called_without_allocate_ = true;
184       }
185       return std::allocator<T>::deallocate(p, n);
186    }
187 };
188 
test_merge_empty_free()189 bool test_merge_empty_free()
190 {
191    vector<int> source;
192    source.emplace_back(1);
193 
194    vector< int, check_dealloc_allocator<int> > empty;
195    empty.merge(source.begin(), source.end());
196 
197    return empty.get_stored_allocator().deallocate_called_without_allocate_;
198 }
199 
main()200 int main()
201 {
202    {
203       const std::size_t positions_length = 10;
204       std::size_t positions[positions_length];
205       vector<int> vector_int;
206       vector<int> vector_int2(positions_length);
207       for(std::size_t i = 0; i != positions_length; ++i){
208          positions[i] = 0u;
209       }
210       for(std::size_t i = 0, max = vector_int2.size(); i != max; ++i){
211          vector_int2[i] = (int)i;
212       }
213 
214       vector_int.insert(vector_int.begin(), 999);
215 
216       vector_int.insert_ordered_at(positions_length, positions + positions_length, vector_int2.end());
217 
218       for(std::size_t i = 0, max = vector_int.size(); i != max; ++i){
219          std::cout << vector_int[i] << std::endl;
220       }
221    }
222    recursive_vector_test();
223    {
224       //Now test move semantics
225       vector<recursive_vector> original;
226       vector<recursive_vector> move_ctor(boost::move(original));
227       vector<recursive_vector> move_assign;
228       move_assign = boost::move(move_ctor);
229       move_assign.swap(original);
230    }
231 
232    ////////////////////////////////////
233    //    Testing allocator implementations
234    ////////////////////////////////////
235    //       std:allocator
236    if(test_cont_variants< std::allocator<void> >()){
237       std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
238       return 1;
239    }
240    //       boost::container::allocator
241    if(test_cont_variants< allocator<void> >()){
242       std::cerr << "test_cont_variants< allocator<void> > failed" << std::endl;
243       return 1;
244    }
245 
246    {
247       typedef vector<Test, std::allocator<Test> > MyEnumCont;
248       MyEnumCont v;
249       Test t;
250       v.push_back(t);
251       v.push_back(::boost::move(t));
252       v.push_back(Test());
253    }
254 
255    if (test_smart_ref_type())
256       return 1;
257 
258    ////////////////////////////////////
259    //    Backwards expansion test
260    ////////////////////////////////////
261    if(test_expand_bwd())
262       return 1;
263 
264    ////////////////////////////////////
265    //    Default init test
266    ////////////////////////////////////
267    if(!test::default_init_test< vector<int, test::default_init_allocator<int> > >()){
268       std::cerr << "Default init test failed" << std::endl;
269       return 1;
270    }
271 
272    ////////////////////////////////////
273    //    Emplace testing
274    ////////////////////////////////////
275    const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE);
276    if(!boost::container::test::test_emplace< vector<test::EmplaceInt>, Options>()){
277       return 1;
278    }
279 
280    ////////////////////////////////////
281    //    Allocator propagation testing
282    ////////////////////////////////////
283    if(!boost::container::test::test_propagate_allocator<boost_container_vector>()){
284       return 1;
285    }
286 
287    ////////////////////////////////////
288    //    Initializer lists testing
289    ////////////////////////////////////
290    if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for<
291        boost::container::vector<int>
292    >()) {
293       return 1;
294    }
295 
296    ////////////////////////////////////
297    //    Iterator testing
298    ////////////////////////////////////
299    {
300       typedef boost::container::vector<int> cont_int;
301       cont_int a; a.push_back(0); a.push_back(1); a.push_back(2);
302       boost::intrusive::test::test_iterator_random< cont_int >(a);
303       if(boost::report_errors() != 0) {
304          return 1;
305       }
306    }
307 
308 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
309    ////////////////////////////////////
310    //    Constructor Template Auto Deduction testing
311    ////////////////////////////////////
312    {
313       auto gold = std::vector{ 1, 2, 3 };
314       auto test = boost::container::vector(gold.begin(), gold.end());
315       if (test.size() != 3) {
316          return 1;
317       }
318       if (!(test[0] == 1 && test[1] == 2 && test[2] == 3)) {
319          return 1;
320       }
321    }
322    {
323       auto gold = std::vector{ 1, 2, 3 };
324       auto test = boost::container::vector(gold.begin(), gold.end(), boost::container::new_allocator<int>());
325       if (test.size() != 3) {
326          return 1;
327       }
328       if (!(test[0] == 1 && test[1] == 2 && test[2] == 3)) {
329          return 1;
330       }
331    }
332 #endif
333 
334    if (test_merge_empty_free()) {
335       std::cerr << "Merge into empty vector test failed" << std::endl;
336       return 1;
337    }
338 
339    ////////////////////////////////////
340    //    has_trivial_destructor_after_move testing
341    ////////////////////////////////////
342    // default allocator
343    {
344       typedef boost::container::vector<int> cont;
345       typedef cont::allocator_type allocator_type;
346       typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
347       BOOST_STATIC_ASSERT_MSG
348          ( !boost::has_trivial_destructor_after_move<pointer>::value ||
349            (boost::has_trivial_destructor_after_move<cont>::value ==
350             boost::has_trivial_destructor_after_move<allocator_type>::value)
351          , "has_trivial_destructor_after_move(default allocator) test failed"
352          );
353    }
354    // std::allocator
355    {
356       typedef boost::container::vector<int, std::allocator<int> > cont;
357       typedef cont::allocator_type allocator_type;
358       typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
359       BOOST_STATIC_ASSERT_MSG
360          ( !boost::has_trivial_destructor_after_move<pointer>::value ||
361            (boost::has_trivial_destructor_after_move<cont>::value ==
362             boost::has_trivial_destructor_after_move<allocator_type>::value)
363          , "has_trivial_destructor_after_move(std::allocator) test failed"
364          );
365    }
366 
367    return 0;
368 }
369