]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // | |
3 | // (C) Copyright Ion Gaztanaga 2011-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 | #include <boost/container/detail/config_begin.hpp> | |
11 | #include <cstddef> | |
12 | #include <boost/container/allocator_traits.hpp> | |
13 | #include <boost/static_assert.hpp> | |
14 | #include <boost/container/detail/type_traits.hpp> | |
15 | #include <boost/container/detail/function_detector.hpp> | |
16 | #include <boost/move/utility_core.hpp> | |
17 | #include <memory> | |
18 | #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
19 | #include <boost/move/detail/fwd_macros.hpp> | |
20 | #endif | |
21 | #include <boost/core/lightweight_test.hpp> | |
22 | ||
23 | template<class T> | |
24 | class SimpleAllocator | |
25 | { | |
26 | public: | |
27 | bool allocate_called_; | |
28 | bool deallocate_called_; | |
29 | ||
11fdf7f2 | 30 | typedef boost::container::dtl:: |
7c673cae FG |
31 | true_type is_always_equal; |
32 | ||
33 | typedef T value_type; | |
34 | ||
35 | template <class U> | |
36 | SimpleAllocator(SimpleAllocator<U>) | |
37 | : allocate_called_(false) | |
38 | , deallocate_called_(false) | |
39 | {} | |
40 | ||
41 | SimpleAllocator() | |
42 | : allocate_called_(false) | |
43 | , deallocate_called_(false) | |
44 | {} | |
45 | ||
46 | T* allocate(std::size_t) | |
47 | { allocate_called_ = true; return 0; } | |
48 | ||
49 | void deallocate(T*, std::size_t) | |
50 | { deallocate_called_ = true; } | |
51 | ||
52 | bool allocate_called() const | |
53 | { return allocate_called_; } | |
54 | ||
55 | bool deallocate_called() const | |
56 | { return deallocate_called_; } | |
57 | ||
58 | friend bool operator==(const SimpleAllocator &, const SimpleAllocator &) | |
59 | { return true; } | |
60 | ||
61 | friend bool operator!=(const SimpleAllocator &, const SimpleAllocator &) | |
62 | { return false; } | |
63 | }; | |
64 | ||
65 | template<class T> | |
66 | class SimpleSmartPtr | |
67 | { | |
68 | void unspecified_bool_type_func() const {} | |
69 | typedef void (SimpleSmartPtr::*unspecified_bool_type)() const; | |
70 | ||
71 | public: | |
72 | ||
73 | typedef T* pointer; | |
74 | ||
75 | explicit SimpleSmartPtr(pointer p = 0) | |
76 | : ptr_(p) | |
77 | {} | |
78 | ||
79 | SimpleSmartPtr(const SimpleSmartPtr &c) | |
80 | { this->ptr_ = c.ptr_; } | |
81 | ||
82 | SimpleSmartPtr & operator=(const SimpleSmartPtr &c) | |
83 | { this->ptr_ = c.ptr_; } | |
84 | ||
85 | operator unspecified_bool_type() const | |
86 | { return ptr_? &SimpleSmartPtr::unspecified_bool_type_func : 0; } | |
87 | ||
88 | private: | |
89 | T *ptr_; | |
90 | }; | |
91 | ||
92 | template<class T> | |
93 | class ComplexAllocator | |
94 | { | |
95 | public: | |
96 | bool allocate_called_; | |
97 | bool deallocate_called_; | |
98 | bool allocate_hint_called_; | |
99 | bool destroy_called_; | |
100 | mutable bool max_size_called_; | |
101 | mutable bool select_on_container_copy_construction_called_; | |
102 | bool construct_called_; | |
103 | mutable bool storage_is_unpropagable_; | |
104 | ||
105 | typedef T value_type; | |
106 | typedef SimpleSmartPtr<T> pointer; | |
107 | typedef SimpleSmartPtr<const T> const_pointer; | |
108 | typedef typename ::boost::container:: | |
11fdf7f2 | 109 | dtl::unvoid_ref<T>::type reference; |
7c673cae | 110 | typedef typename ::boost::container:: |
11fdf7f2 | 111 | dtl::unvoid_ref<const T>::type const_reference; |
7c673cae FG |
112 | typedef SimpleSmartPtr<void> void_pointer; |
113 | typedef SimpleSmartPtr<const void> const_void_pointer; | |
114 | typedef signed short difference_type; | |
115 | typedef unsigned short size_type; | |
11fdf7f2 | 116 | typedef boost::container::dtl:: |
7c673cae | 117 | true_type propagate_on_container_copy_assignment; |
11fdf7f2 | 118 | typedef boost::container::dtl:: |
7c673cae | 119 | true_type propagate_on_container_move_assignment; |
11fdf7f2 | 120 | typedef boost::container::dtl:: |
7c673cae | 121 | true_type propagate_on_container_swap; |
11fdf7f2 | 122 | typedef boost::container::dtl:: |
7c673cae FG |
123 | true_type is_partially_propagable; |
124 | ||
125 | ComplexAllocator() | |
126 | : allocate_called_(false) | |
127 | , deallocate_called_(false) | |
128 | , allocate_hint_called_(false) | |
129 | , destroy_called_(false) | |
130 | , max_size_called_(false) | |
131 | , select_on_container_copy_construction_called_(false) | |
132 | , construct_called_(false) | |
133 | {} | |
134 | ||
135 | pointer allocate(size_type) | |
136 | { allocate_called_ = true; return pointer(); } | |
137 | ||
138 | void deallocate(pointer, size_type) | |
139 | { deallocate_called_ = true; } | |
140 | ||
141 | //optional | |
142 | ComplexAllocator select_on_container_copy_construction() const | |
143 | { select_on_container_copy_construction_called_ = true; return *this; } | |
144 | ||
145 | pointer allocate(size_type n, const const_void_pointer &) | |
146 | { allocate_hint_called_ = true; return allocate(n); } | |
147 | ||
148 | template<class U> | |
149 | void destroy(U*) | |
150 | { destroy_called_ = true; } | |
151 | ||
152 | size_type max_size() const | |
153 | { max_size_called_ = true; return size_type(size_type(0)-1); } | |
154 | ||
155 | #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
156 | ||
157 | #define BOOST_CONTAINER_COMPLEXALLOCATOR_CONSTRUCT_IMPL(N)\ | |
158 | \ | |
159 | template< class U BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \ | |
160 | void construct(U *p BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \ | |
161 | { construct_called_ = true; ::new(p) U ( BOOST_MOVE_FWD##N ); }\ | |
162 | // | |
163 | BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_COMPLEXALLOCATOR_CONSTRUCT_IMPL) | |
164 | #undef BOOST_CONTAINER_COMPLEXALLOCATOR_CONSTRUCT_IMPL | |
165 | #else | |
166 | ||
167 | template< class U, class ...Args> | |
168 | void construct(U *p, BOOST_FWD_REF(Args) ...args) | |
169 | { construct_called_ = true; ::new(p) U( ::boost::forward<Args>(args)...); } | |
170 | ||
171 | #endif | |
172 | ||
173 | template<class U> | |
174 | void construct(U *p, boost::container::default_init_t) | |
175 | { construct_called_ = true; ::new(p)U; } | |
176 | ||
177 | bool storage_is_unpropagable(pointer p) const | |
178 | { storage_is_unpropagable_ = true; return !p; } | |
179 | ||
180 | //getters | |
181 | bool allocate_called() const | |
182 | { return allocate_called_; } | |
183 | ||
184 | bool deallocate_called() const | |
185 | { return deallocate_called_; } | |
186 | ||
187 | bool allocate_hint_called() const | |
188 | { return allocate_hint_called_; } | |
189 | ||
190 | bool destroy_called() const | |
191 | { return destroy_called_; } | |
192 | ||
193 | bool max_size_called() const | |
194 | { return max_size_called_; } | |
195 | ||
196 | bool select_on_container_copy_construction_called() const | |
197 | { return select_on_container_copy_construction_called_; } | |
198 | ||
199 | bool construct_called() const | |
200 | { return construct_called_; } | |
201 | ||
202 | bool storage_is_unpropagable_called() const | |
203 | { return storage_is_unpropagable_; } | |
204 | }; | |
205 | ||
206 | class copymovable | |
207 | { | |
208 | BOOST_COPYABLE_AND_MOVABLE(copymovable) | |
209 | ||
210 | public: | |
211 | ||
212 | bool copymoveconstructed_; | |
213 | bool moved_; | |
214 | ||
215 | copymovable(int, int, int) | |
216 | : copymoveconstructed_(false), moved_(false) | |
217 | {} | |
218 | ||
219 | copymovable() | |
220 | : copymoveconstructed_(false), moved_(false) | |
221 | {} | |
222 | ||
223 | copymovable(const copymovable &) | |
224 | : copymoveconstructed_(true), moved_(false) | |
225 | {} | |
226 | ||
227 | copymovable(BOOST_RV_REF(copymovable)) | |
228 | : copymoveconstructed_(true), moved_(true) | |
229 | {} | |
230 | ||
231 | copymovable & operator=(BOOST_COPY_ASSIGN_REF(copymovable) ){ return *this; } | |
232 | copymovable & operator=(BOOST_RV_REF(copymovable) ){ return *this; } | |
233 | ||
234 | bool copymoveconstructed() const | |
235 | { return copymoveconstructed_; } | |
236 | ||
237 | bool moved() const | |
238 | { return moved_; } | |
239 | }; | |
240 | ||
241 | void test_void_allocator() | |
242 | { | |
243 | boost::container::allocator_traits<std::allocator<void> > stdtraits; (void)stdtraits; | |
244 | boost::container::allocator_traits<SimpleAllocator<void> > simtraits; (void)simtraits; | |
245 | boost::container::allocator_traits<ComplexAllocator<void> > comtraits; (void)comtraits; | |
246 | } | |
247 | ||
248 | int main() | |
249 | { | |
11fdf7f2 | 250 | using namespace boost::container::dtl; |
7c673cae FG |
251 | test_void_allocator(); |
252 | ||
253 | //SimpleAllocator | |
254 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
255 | < SimpleAllocator<int> >::value_type, int>::value )); | |
256 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
257 | < SimpleAllocator<int> >::pointer, int*>::value )); | |
258 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
259 | < SimpleAllocator<int> >::const_pointer, const int*>::value )); | |
260 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
261 | < SimpleAllocator<int> >::void_pointer, void*>::value )); | |
262 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
263 | < SimpleAllocator<int> >::const_void_pointer, const void*>::value )); | |
264 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
265 | < SimpleAllocator<int> >::difference_type, std::ptrdiff_t>::value )); | |
266 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
267 | < SimpleAllocator<int> >::size_type, std::size_t>::value )); | |
268 | BOOST_STATIC_ASSERT(( boost::container::allocator_traits | |
269 | < SimpleAllocator<int> >::propagate_on_container_copy_assignment::value == false )); | |
270 | BOOST_STATIC_ASSERT(( boost::container::allocator_traits | |
271 | < SimpleAllocator<int> >::propagate_on_container_move_assignment::value == false )); | |
272 | BOOST_STATIC_ASSERT(( boost::container::allocator_traits | |
273 | < SimpleAllocator<int> >::propagate_on_container_swap::value == false )); | |
274 | BOOST_STATIC_ASSERT(( boost::container::allocator_traits | |
275 | < SimpleAllocator<int> >::is_always_equal::value == true )); | |
276 | BOOST_STATIC_ASSERT(( boost::container::allocator_traits | |
277 | < SimpleAllocator<int> >::is_partially_propagable::value == false )); | |
278 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
279 | < SimpleAllocator<int> >::rebind_traits<double>::allocator_type | |
280 | , SimpleAllocator<double> >::value )); | |
281 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
282 | < SimpleAllocator<int> >::rebind_alloc<double>::value_type | |
283 | , double >::value )); | |
284 | ||
285 | //ComplexAllocator | |
286 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
287 | < ComplexAllocator<int> >::value_type, int>::value )); | |
288 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
289 | < ComplexAllocator<int> >::pointer, SimpleSmartPtr<int> >::value )); | |
290 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
291 | < ComplexAllocator<int> >::const_pointer, SimpleSmartPtr<const int> >::value )); | |
292 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
293 | < ComplexAllocator<int> >::void_pointer, SimpleSmartPtr<void> >::value )); | |
294 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
295 | < ComplexAllocator<int> >::const_void_pointer, SimpleSmartPtr<const void> >::value )); | |
296 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
297 | < ComplexAllocator<int> >::difference_type, signed short>::value )); | |
298 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
299 | < ComplexAllocator<int> >::size_type, unsigned short>::value )); | |
300 | BOOST_STATIC_ASSERT(( boost::container::allocator_traits | |
301 | < ComplexAllocator<int> >::propagate_on_container_copy_assignment::value == true )); | |
302 | BOOST_STATIC_ASSERT(( boost::container::allocator_traits | |
303 | < ComplexAllocator<int> >::propagate_on_container_move_assignment::value == true )); | |
304 | BOOST_STATIC_ASSERT(( boost::container::allocator_traits | |
305 | < ComplexAllocator<int> >::propagate_on_container_swap::value == true )); | |
306 | BOOST_STATIC_ASSERT(( boost::container::allocator_traits | |
307 | < ComplexAllocator<int> >::is_always_equal::value == false )); | |
308 | BOOST_STATIC_ASSERT(( boost::container::allocator_traits | |
309 | < ComplexAllocator<int> >::is_partially_propagable::value == true )); | |
310 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
311 | < ComplexAllocator<int> >::rebind_traits<double>::allocator_type | |
312 | , ComplexAllocator<double> >::value )); | |
313 | BOOST_STATIC_ASSERT(( is_same<boost::container::allocator_traits | |
314 | < ComplexAllocator<int> >::rebind_alloc<double>::value_type | |
315 | , double >::value )); | |
316 | ||
317 | typedef ComplexAllocator<int> CAlloc; | |
318 | typedef SimpleAllocator<int> SAlloc; | |
319 | typedef boost::container::allocator_traits<CAlloc> CAllocTraits; | |
320 | typedef boost::container::allocator_traits<SAlloc> SAllocTraits; | |
321 | CAlloc c_alloc; | |
322 | SAlloc s_alloc; | |
323 | ||
324 | //allocate | |
325 | CAllocTraits::allocate(c_alloc, 1); | |
326 | BOOST_TEST(c_alloc.allocate_called()); | |
327 | ||
328 | SAllocTraits::allocate(s_alloc, 1); | |
329 | BOOST_TEST(s_alloc.allocate_called()); | |
330 | ||
331 | //deallocate | |
332 | CAllocTraits::deallocate(c_alloc, CAllocTraits::pointer(), 1); | |
333 | BOOST_TEST(c_alloc.deallocate_called()); | |
334 | ||
335 | SAllocTraits::deallocate(s_alloc, SAllocTraits::pointer(), 1); | |
336 | BOOST_TEST(s_alloc.deallocate_called()); | |
337 | ||
338 | //allocate with hint | |
339 | CAllocTraits::allocate(c_alloc, 1, CAllocTraits::const_void_pointer()); | |
340 | BOOST_TEST(c_alloc.allocate_hint_called()); | |
341 | ||
342 | s_alloc.allocate_called_ = false; | |
343 | SAllocTraits::allocate(s_alloc, 1, SAllocTraits::const_void_pointer()); | |
344 | BOOST_TEST(s_alloc.allocate_called()); | |
345 | ||
346 | //destroy | |
347 | float dummy; | |
348 | CAllocTraits::destroy(c_alloc, &dummy); | |
349 | BOOST_TEST(c_alloc.destroy_called()); | |
350 | ||
351 | SAllocTraits::destroy(s_alloc, &dummy); | |
352 | ||
353 | //max_size | |
354 | CAllocTraits::max_size(c_alloc); | |
355 | BOOST_TEST(c_alloc.max_size_called()); | |
356 | ||
357 | BOOST_TEST(SAllocTraits::size_type(-1)/sizeof(SAllocTraits::value_type) == SAllocTraits::max_size(s_alloc)); | |
358 | ||
359 | //select_on_container_copy_construction | |
360 | CAllocTraits::select_on_container_copy_construction(c_alloc); | |
361 | BOOST_TEST(c_alloc.select_on_container_copy_construction_called()); | |
362 | ||
363 | SAllocTraits::select_on_container_copy_construction(s_alloc); | |
364 | ||
365 | //construct | |
366 | { | |
367 | copymovable c; | |
368 | c.copymoveconstructed_ = true; | |
369 | c.copymoveconstructed_ = true; | |
370 | CAllocTraits::construct(c_alloc, &c); | |
371 | BOOST_TEST(c_alloc.construct_called() && !c.copymoveconstructed() && !c.moved()); | |
372 | } | |
373 | { | |
374 | int i = 5; | |
375 | CAllocTraits::construct(c_alloc, &i, boost::container::default_init); | |
376 | BOOST_TEST(c_alloc.construct_called() && i == 5); | |
377 | } | |
378 | { | |
379 | copymovable c; | |
380 | copymovable c2; | |
381 | CAllocTraits::construct(c_alloc, &c, c2); | |
382 | BOOST_TEST(c_alloc.construct_called() && c.copymoveconstructed() && !c.moved()); | |
383 | } | |
384 | { | |
385 | copymovable c; | |
386 | copymovable c2; | |
387 | CAllocTraits::construct(c_alloc, &c, ::boost::move(c2)); | |
388 | BOOST_TEST(c_alloc.construct_called() && c.copymoveconstructed() && c.moved()); | |
389 | } | |
390 | { | |
391 | copymovable c; | |
392 | c.copymoveconstructed_ = true; | |
393 | c.copymoveconstructed_ = true; | |
394 | SAllocTraits::construct(s_alloc, &c); | |
395 | BOOST_TEST(!c.copymoveconstructed() && !c.moved()); | |
396 | } | |
397 | { | |
398 | int i = 4; | |
399 | SAllocTraits::construct(s_alloc, &i, boost::container::default_init); | |
400 | BOOST_TEST(i == 4); | |
401 | } | |
402 | { | |
403 | copymovable c; | |
404 | copymovable c2; | |
405 | SAllocTraits::construct(s_alloc, &c, c2); | |
406 | BOOST_TEST(c.copymoveconstructed() && !c.moved()); | |
407 | } | |
408 | { | |
409 | copymovable c; | |
410 | copymovable c2; | |
411 | SAllocTraits::construct(s_alloc, &c, ::boost::move(c2)); | |
412 | BOOST_TEST(c.copymoveconstructed() && c.moved()); | |
413 | } | |
414 | { | |
415 | copymovable c; | |
416 | CAllocTraits::construct(c_alloc, &c, 0, 1, 2); | |
417 | BOOST_TEST(c_alloc.construct_called() && !c.copymoveconstructed() && !c.moved()); | |
418 | } | |
419 | { | |
420 | copymovable c; | |
421 | copymovable c2; | |
422 | SAllocTraits::construct(s_alloc, &c, 0, 1, 2); | |
423 | BOOST_TEST(!c.copymoveconstructed() && !c.moved()); | |
424 | } | |
425 | //storage_is_unpropagable | |
426 | { | |
427 | SAlloc s_alloc2; | |
428 | BOOST_TEST(!SAllocTraits::storage_is_unpropagable(s_alloc, SAllocTraits::pointer())); | |
429 | } | |
430 | { | |
431 | { | |
432 | CAlloc c_alloc2; | |
433 | CAlloc::value_type v; | |
434 | BOOST_TEST(!CAllocTraits::storage_is_unpropagable(c_alloc, CAllocTraits::pointer(&v))); | |
435 | BOOST_TEST(c_alloc.storage_is_unpropagable_called()); | |
436 | } | |
437 | { | |
438 | CAlloc c_alloc2; | |
439 | BOOST_TEST( CAllocTraits::storage_is_unpropagable(c_alloc2, CAllocTraits::pointer())); | |
440 | BOOST_TEST(c_alloc2.storage_is_unpropagable_called()); | |
441 | } | |
442 | ||
443 | } | |
444 | ||
445 | return ::boost::report_errors(); | |
446 | } | |
447 | #include <boost/container/detail/config_end.hpp> |