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

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