]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ////////////////////////////////////////////////////////////////////////////// | |
11fdf7f2 TL |
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 | ||
7c673cae FG |
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 | ||
7c673cae FG |
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 | ||
92f5a8d4 TL |
59 | struct X; |
60 | ||
61 | template<typename T> | |
62 | struct XRef | |
63 | { | |
1e59de90 | 64 | explicit XRef(T* p) : ptr(p) {} |
92f5a8d4 TL |
65 | operator T*() const { return ptr; } |
66 | T* ptr; | |
67 | }; | |
68 | ||
69 | struct X | |
70 | { | |
71 | XRef<X const> operator&() const { return XRef<X const>(this); } | |
72 | XRef<X> operator&() { return XRef<X>(this); } | |
73 | }; | |
74 | ||
75 | ||
76 | bool test_smart_ref_type() | |
77 | { | |
78 | boost::container::vector<X> x(5); | |
79 | return x.empty(); | |
80 | } | |
81 | ||
7c673cae FG |
82 | class recursive_vector |
83 | { | |
84 | public: | |
20effc67 TL |
85 | recursive_vector (const recursive_vector &x) |
86 | : vector_(x.vector_) | |
87 | {} | |
88 | ||
7c673cae FG |
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 | ||
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> | |
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 | ||
92f5a8d4 TL |
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 | ||
166 | check_dealloc_allocator() | |
167 | : std::allocator<T>() | |
168 | , allocate_zero_called_(false) | |
169 | , deallocate_called_without_allocate_(false) | |
170 | {} | |
171 | ||
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 | ||
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 | ||
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 | ||
1e59de90 | 197 | return !empty.get_stored_allocator().deallocate_called_without_allocate_; |
92f5a8d4 TL |
198 | } |
199 | ||
1e59de90 TL |
200 | #if defined(__cpp_lib_span) |
201 | # define BOOST_VECTOR_TEST_HAS_SPAN | |
202 | #endif | |
203 | ||
204 | #ifdef BOOST_VECTOR_TEST_HAS_SPAN | |
205 | #include <span> | |
206 | ||
207 | bool test_span_conversion() | |
208 | { | |
209 | boost::container::vector myVec{1, 2, 3, 4, 5}; | |
210 | std::span mySpan1{myVec}; // (1) | |
211 | std::span mySpan2{myVec.data(), myVec.size()}; // (2) | |
212 | return mySpan1.size() == myVec.size() && mySpan1.size() == mySpan2.size(); | |
213 | } | |
214 | ||
215 | #else //BOOST_VECTOR_TEST_HAS_SPAN | |
216 | bool test_span_conversion() | |
217 | { | |
218 | return true; | |
219 | } | |
220 | ||
221 | #endif //BOOST_VECTOR_TEST_HAS_SPAN | |
222 | ||
7c673cae FG |
223 | int main() |
224 | { | |
225 | { | |
226 | const std::size_t positions_length = 10; | |
227 | std::size_t positions[positions_length]; | |
228 | vector<int> vector_int; | |
229 | vector<int> vector_int2(positions_length); | |
230 | for(std::size_t i = 0; i != positions_length; ++i){ | |
231 | positions[i] = 0u; | |
232 | } | |
233 | for(std::size_t i = 0, max = vector_int2.size(); i != max; ++i){ | |
234 | vector_int2[i] = (int)i; | |
235 | } | |
236 | ||
237 | vector_int.insert(vector_int.begin(), 999); | |
238 | ||
239 | vector_int.insert_ordered_at(positions_length, positions + positions_length, vector_int2.end()); | |
240 | ||
241 | for(std::size_t i = 0, max = vector_int.size(); i != max; ++i){ | |
242 | std::cout << vector_int[i] << std::endl; | |
243 | } | |
244 | } | |
245 | recursive_vector_test(); | |
246 | { | |
247 | //Now test move semantics | |
248 | vector<recursive_vector> original; | |
249 | vector<recursive_vector> move_ctor(boost::move(original)); | |
250 | vector<recursive_vector> move_assign; | |
251 | move_assign = boost::move(move_ctor); | |
252 | move_assign.swap(original); | |
253 | } | |
254 | ||
255 | //////////////////////////////////// | |
256 | // Testing allocator implementations | |
257 | //////////////////////////////////// | |
258 | // std:allocator | |
259 | if(test_cont_variants< std::allocator<void> >()){ | |
260 | std::cerr << "test_cont_variants< std::allocator<void> > failed" << std::endl; | |
261 | return 1; | |
262 | } | |
263 | // boost::container::allocator | |
264 | if(test_cont_variants< allocator<void> >()){ | |
265 | std::cerr << "test_cont_variants< allocator<void> > failed" << std::endl; | |
266 | return 1; | |
267 | } | |
268 | ||
269 | { | |
270 | typedef vector<Test, std::allocator<Test> > MyEnumCont; | |
271 | MyEnumCont v; | |
272 | Test t; | |
273 | v.push_back(t); | |
274 | v.push_back(::boost::move(t)); | |
275 | v.push_back(Test()); | |
276 | } | |
277 | ||
92f5a8d4 TL |
278 | if (test_smart_ref_type()) |
279 | return 1; | |
280 | ||
7c673cae FG |
281 | //////////////////////////////////// |
282 | // Backwards expansion test | |
283 | //////////////////////////////////// | |
284 | if(test_expand_bwd()) | |
285 | return 1; | |
286 | ||
287 | //////////////////////////////////// | |
288 | // Default init test | |
289 | //////////////////////////////////// | |
290 | if(!test::default_init_test< vector<int, test::default_init_allocator<int> > >()){ | |
291 | std::cerr << "Default init test failed" << std::endl; | |
292 | return 1; | |
293 | } | |
294 | ||
295 | //////////////////////////////////// | |
296 | // Emplace testing | |
297 | //////////////////////////////////// | |
298 | const test::EmplaceOptions Options = (test::EmplaceOptions)(test::EMPLACE_BACK | test::EMPLACE_BEFORE); | |
299 | if(!boost::container::test::test_emplace< vector<test::EmplaceInt>, Options>()){ | |
300 | return 1; | |
301 | } | |
302 | ||
303 | //////////////////////////////////// | |
304 | // Allocator propagation testing | |
305 | //////////////////////////////////// | |
306 | if(!boost::container::test::test_propagate_allocator<boost_container_vector>()){ | |
307 | return 1; | |
308 | } | |
309 | ||
310 | //////////////////////////////////// | |
311 | // Initializer lists testing | |
312 | //////////////////////////////////// | |
313 | if(!boost::container::test::test_vector_methods_with_initializer_list_as_argument_for< | |
314 | boost::container::vector<int> | |
315 | >()) { | |
316 | return 1; | |
317 | } | |
318 | ||
319 | //////////////////////////////////// | |
320 | // Iterator testing | |
321 | //////////////////////////////////// | |
322 | { | |
323 | typedef boost::container::vector<int> cont_int; | |
324 | cont_int a; a.push_back(0); a.push_back(1); a.push_back(2); | |
325 | boost::intrusive::test::test_iterator_random< cont_int >(a); | |
326 | if(boost::report_errors() != 0) { | |
327 | return 1; | |
328 | } | |
329 | } | |
92f5a8d4 TL |
330 | |
331 | #ifndef BOOST_CONTAINER_NO_CXX17_CTAD | |
332 | //////////////////////////////////// | |
333 | // Constructor Template Auto Deduction testing | |
334 | //////////////////////////////////// | |
335 | { | |
336 | auto gold = std::vector{ 1, 2, 3 }; | |
337 | auto test = boost::container::vector(gold.begin(), gold.end()); | |
338 | if (test.size() != 3) { | |
339 | return 1; | |
340 | } | |
341 | if (!(test[0] == 1 && test[1] == 2 && test[2] == 3)) { | |
342 | return 1; | |
343 | } | |
344 | } | |
345 | { | |
346 | auto gold = std::vector{ 1, 2, 3 }; | |
347 | auto test = boost::container::vector(gold.begin(), gold.end(), boost::container::new_allocator<int>()); | |
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 | #endif | |
356 | ||
1e59de90 | 357 | if (!test_merge_empty_free()) { |
92f5a8d4 TL |
358 | std::cerr << "Merge into empty vector test failed" << std::endl; |
359 | return 1; | |
360 | } | |
361 | ||
1e59de90 TL |
362 | if (!test_span_conversion()) { |
363 | std::cerr << "Span conversion failed" << std::endl; | |
364 | return 1; | |
365 | } | |
366 | ||
92f5a8d4 TL |
367 | //////////////////////////////////// |
368 | // has_trivial_destructor_after_move testing | |
369 | //////////////////////////////////// | |
370 | // default allocator | |
371 | { | |
372 | typedef boost::container::vector<int> cont; | |
373 | typedef cont::allocator_type allocator_type; | |
374 | typedef boost::container::allocator_traits<allocator_type>::pointer pointer; | |
20effc67 TL |
375 | BOOST_STATIC_ASSERT_MSG |
376 | ( !boost::has_trivial_destructor_after_move<pointer>::value || | |
377 | (boost::has_trivial_destructor_after_move<cont>::value == | |
378 | boost::has_trivial_destructor_after_move<allocator_type>::value) | |
379 | , "has_trivial_destructor_after_move(default allocator) test failed" | |
380 | ); | |
92f5a8d4 TL |
381 | } |
382 | // std::allocator | |
383 | { | |
384 | typedef boost::container::vector<int, std::allocator<int> > cont; | |
385 | typedef cont::allocator_type allocator_type; | |
386 | typedef boost::container::allocator_traits<allocator_type>::pointer pointer; | |
20effc67 TL |
387 | BOOST_STATIC_ASSERT_MSG |
388 | ( !boost::has_trivial_destructor_after_move<pointer>::value || | |
389 | (boost::has_trivial_destructor_after_move<cont>::value == | |
390 | boost::has_trivial_destructor_after_move<allocator_type>::value) | |
391 | , "has_trivial_destructor_after_move(std::allocator) test failed" | |
392 | ); | |
92f5a8d4 TL |
393 | } |
394 | ||
7c673cae FG |
395 | return 0; |
396 | } |