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
34using namespace boost::container;
35
36int 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
59struct X;
60
61template<typename T>
62struct XRef
63{
64 explicit XRef(T* p) : ptr(p) {}
65 operator T*() const { return ptr; }
66 T* ptr;
67};
68
69struct X
70{
71 XRef<X const> operator&() const { return XRef<X const>(this); }
72 XRef<X> operator&() { return XRef<X>(this); }
73};
74
75
76bool test_smart_ref_type()
77{
78 boost::container::vector<X> x(5);
79 return x.empty();
80}
81
82class recursive_vector
83{
84 public:
85 recursive_vector (const recursive_vector &x)
86 : vector_(x.vector_)
87 {}
88
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
100void recursive_vector_test()//Test for recursive types
101{
102 vector<recursive_vector> recursive_vector_vector;
103}
104
105enum Test
106{
107 zero, one, two, three, four, five, six
108};
109
110template<class VoidAllocator>
111struct 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
123template<class VoidAllocator>
124int 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 typedef typename GetAllocatorCont<VoidAllocator>::template apply<test::moveconstruct_int>::type MyMoveConstructCont;
131
132 if(test::vector_test<MyCont>())
133 return 1;
134 if(test::vector_test<MyMoveCont>())
135 return 1;
136 if(test::vector_test<MyCopyMoveCont>())
137 return 1;
138 if(test::vector_test<MyCopyCont>())
139 return 1;
140 if (test::vector_test<MyMoveConstructCont>())
141 return 1;
142
143 return 0;
144}
145
146struct boost_container_vector;
147
148namespace boost { namespace container { namespace test {
149
150template<>
151struct alloc_propagate_base<boost_container_vector>
152{
153 template <class T, class Allocator>
154 struct apply
155 {
156 typedef boost::container::vector<T, Allocator> type;
157 };
158};
159
160}}} //namespace boost::container::test
161
162template<typename T>
163class check_dealloc_allocator : public std::allocator<T>
164{
165 public:
166 bool allocate_zero_called_;
167 bool deallocate_called_without_allocate_;
168
169 check_dealloc_allocator()
170 : std::allocator<T>()
171 , allocate_zero_called_(false)
172 , deallocate_called_without_allocate_(false)
173 {}
174
175 T* allocate(std::size_t n)
176 {
177 if (n == 0) {
178 allocate_zero_called_ = true;
179 }
180 return std::allocator<T>::allocate(n);
181 }
182
183 void deallocate(T* p, std::size_t n)
184 {
185 if (n == 0 && !allocate_zero_called_) {
186 deallocate_called_without_allocate_ = true;
187 }
188 return std::allocator<T>::deallocate(p, n);
189 }
190};
191
192bool test_merge_empty_free()
193{
194 vector<int> source;
195 source.emplace_back(args: 1);
196
197 vector< int, check_dealloc_allocator<int> > empty;
198 empty.merge(first: source.begin(), last: source.end());
199
200 return !empty.get_stored_allocator().deallocate_called_without_allocate_;
201}
202
203#if defined(__cpp_lib_span) && (!defined(_LIBCPP_VERSION) || (_LIBCPP_VERSION >= 15000))
204//libcpp 14 does not correctly support deduction guides for Span
205# define BOOST_VECTOR_TEST_HAS_SPAN
206#endif
207
208#ifdef BOOST_VECTOR_TEST_HAS_SPAN
209#include <span>
210
211bool test_span_conversion()
212{
213 boost::container::vector myVec{1, 2, 3, 4, 5};
214 std::span mySpan1{myVec}; // (1)
215 std::span mySpan2{myVec.data(), myVec.size()}; // (2)
216 return mySpan1.size() == myVec.size() && mySpan1.size() == mySpan2.size();
217}
218
219#else //BOOST_VECTOR_TEST_HAS_SPAN
220bool test_span_conversion()
221{
222 return true;
223}
224
225#endif //BOOST_VECTOR_TEST_HAS_SPAN
226
227struct POD { int POD::*ptr; };
228BOOST_CONTAINER_STATIC_ASSERT_MSG
229 ( boost::container::dtl::is_pod<POD>::value
230 , "POD test failed"
231 );
232
233int main()
234{
235 {
236 const std::size_t positions_length = 10;
237 std::size_t positions[positions_length];
238 vector<int> vector_int;
239 vector<int> vector_int2(positions_length);
240 for(std::size_t i = 0; i != positions_length; ++i){
241 positions[i] = 0u;
242 }
243 for(std::size_t i = 0, max = vector_int2.size(); i != max; ++i){
244 vector_int2[i] = (int)i;
245 }
246
247 vector_int.insert(arg1: vector_int.begin(), x: 999);
248
249 vector_int.insert_ordered_at(element_count: positions_length, last_position_it: positions + positions_length, last_value_it: vector_int2.end());
250
251 for(std::size_t i = 0, max = vector_int.size(); i != max; ++i){
252 std::cout << vector_int[i] << std::endl;
253 }
254 }
255 recursive_vector_test();
256 {
257 //Now test move semantics
258 vector<recursive_vector> original;
259 vector<recursive_vector> move_ctor(boost::move(t&: original));
260 vector<recursive_vector> move_assign;
261 move_assign = boost::move(t&: move_ctor);
262 move_assign.swap(x&: original);
263 }
264
265 ////////////////////////////////////
266 // Testing allocator implementations
267 ////////////////////////////////////
268 // std:allocator
269 if(test_cont_variants< std::allocator<void> >()){
270 std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl;
271 return 1;
272 }
273 // boost::container::allocator
274 if(test_cont_variants< allocator<void> >()){
275 std::cerr << "test_cont_variants< allocator<void> > failed" << std::endl;
276 return 1;
277 }
278
279 { //Test enum container
280 typedef vector<Test, std::allocator<Test> > MyEnumCont;
281 MyEnumCont v;
282 Test t = Test();
283 v.push_back(x: t);
284 v.push_back(x: ::boost::move(t));
285 v.push_back(x: Test());
286 }
287
288 if (test_smart_ref_type())
289 return 1;
290
291 ////////////////////////////////////
292 // Backwards expansion test
293 ////////////////////////////////////
294 if(test_expand_bwd())
295 return 1;
296
297 ////////////////////////////////////
298 // Default init test
299 ////////////////////////////////////
300 if(!test::default_init_test< vector<int, test::default_init_allocator<int> > >()){
301 std::cerr << "Default init test failed" << std::endl;
302 return 1;
303 }
304
305 ////////////////////////////////////
306 // Emplace testing
307 ////////////////////////////////////
308 const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE);
309 if(!boost::container::test::test_emplace< vector<test::EmplaceInt>, Options>()){
310 return 1;
311 }
312
313 ////////////////////////////////////
314 // Allocator propagation testing
315 ////////////////////////////////////
316 if(!boost::container::test::test_propagate_allocator<boost_container_vector>()){
317 return 1;
318 }
319
320 ////////////////////////////////////
321 // Initializer lists testing
322 ////////////////////////////////////
323 if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for<
324 boost::container::vector<int>
325 >()) {
326 return 1;
327 }
328
329 ////////////////////////////////////
330 // Iterator testing
331 ////////////////////////////////////
332 {
333 typedef boost::container::vector<int> cont_int;
334 cont_int a; a.push_back(x: 0); a.push_back(x: 1); a.push_back(x: 2);
335 boost::intrusive::test::test_iterator_random< cont_int >(c&: a);
336 if(boost::report_errors() != 0) {
337 return 1;
338 }
339 }
340
341#ifndef BOOST_CONTAINER_NO_CXX17_CTAD
342 ////////////////////////////////////
343 // Constructor Template Auto Deduction testing
344 ////////////////////////////////////
345 {
346 auto gold = std::vector{ 1, 2, 3 };
347 auto test = boost::container::vector(gold.begin(), gold.end());
348 if (test.size() != 3) {
349 return 1;
350 }
351 if (!(test[0] == 1 && test[1] == 2 && test[2] == 3)) {
352 return 1;
353 }
354 }
355 {
356 auto gold = std::vector{ 1, 2, 3 };
357 auto test = boost::container::vector(gold.begin(), gold.end(), boost::container::new_allocator<int>());
358 if (test.size() != 3) {
359 return 1;
360 }
361 if (!(test[0] == 1 && test[1] == 2 && test[2] == 3)) {
362 return 1;
363 }
364 }
365#endif
366
367 if (!test_merge_empty_free()) {
368 std::cerr << "Merge into empty vector test failed" << std::endl;
369 return 1;
370 }
371
372 if (!test_span_conversion()) {
373 std::cerr << "Span conversion failed" << std::endl;
374 return 1;
375 }
376
377 ////////////////////////////////////
378 // has_trivial_destructor_after_move testing
379 ////////////////////////////////////
380 // default allocator
381 {
382 typedef boost::container::vector<int> cont;
383 typedef cont::allocator_type allocator_type;
384 typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
385 BOOST_CONTAINER_STATIC_ASSERT_MSG
386 ( !boost::has_trivial_destructor_after_move<pointer>::value ||
387 (boost::has_trivial_destructor_after_move<cont>::value ==
388 boost::has_trivial_destructor_after_move<allocator_type>::value)
389 , "has_trivial_destructor_after_move(default allocator) test failed"
390 );
391 }
392 // std::allocator
393 {
394 typedef boost::container::vector<int, std::allocator<int> > cont;
395 typedef cont::allocator_type allocator_type;
396 typedef boost::container::allocator_traits<allocator_type>::pointer pointer;
397 BOOST_CONTAINER_STATIC_ASSERT_MSG
398 ( !boost::has_trivial_destructor_after_move<pointer>::value ||
399 (boost::has_trivial_destructor_after_move<cont>::value ==
400 boost::has_trivial_destructor_after_move<allocator_type>::value)
401 , "has_trivial_destructor_after_move(std::allocator) test failed"
402 );
403 }
404
405 ////////////////////////////////////
406 // POD types should not be 0-filled testing
407 ////////////////////////////////////
408#if !defined(_MSC_VER)
409 // MSVC miscompiles value initialization of pointers to data members,
410 // https://developercommunity.visualstudio.com/t/Pointer-to-data-member-is-not-initialize/10238905
411 {
412 typedef boost::container::vector<POD> cont;
413 const std::size_t size = 10;
414 cont a(size);
415 for(std::size_t i = 0; i != size; ++i) {
416 if (a[i].ptr != 0) {
417 std::cerr << "POD test failed" << std::endl;
418 return 1;
419 }
420 }
421 }
422#endif
423
424 return 0;
425}
426

source code of boost/libs/container/test/vector_test.cpp