Imported Upstream version 1.51.0
[platform/upstream/boost.git] / libs / container / test / allocator_traits_test.cpp
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2011-2012. 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/type_traits/is_same.hpp>
15 #include <boost/type_traits/integral_constant.hpp>
16 #include <boost/container/detail/function_detector.hpp>
17 #include <boost/move/move.hpp>
18 #include <memory>
19
20 template<class T>
21 class SimpleAllocator
22 {
23    bool allocate_called_;
24    bool deallocate_called_;
25    public:
26    typedef T value_type;
27
28    SimpleAllocator()
29       : allocate_called_(false)
30       , deallocate_called_(false)
31    {}
32
33    T* allocate(std::size_t)
34    {  allocate_called_ = true; return 0;  }
35
36    void deallocate(T*, std::size_t)
37    {  deallocate_called_ = true;  }
38
39    bool allocate_called() const
40    {  return allocate_called_;  }
41
42    bool deallocate_called() const
43    {  return deallocate_called_;  }
44 };
45
46 template<class T>
47 class SimpleSmartPtr
48 {
49    public:
50
51    SimpleSmartPtr()
52     : ptr_(0)
53    {}
54
55    SimpleSmartPtr(const SimpleSmartPtr &c)
56    {  this->ptr_ = c.ptr_; }
57
58    SimpleSmartPtr & operator=(const SimpleSmartPtr &c)
59    {  this->ptr_ = c.ptr_; }
60
61    typedef T* pointer;
62
63    private:
64    T *ptr_;
65 };
66
67 template<class T>
68 class ComplexAllocator
69 {
70    bool allocate_called_;
71    bool deallocate_called_;
72    bool allocate_hint_called_;
73    bool destroy_called_;
74    mutable bool max_size_called_;
75    mutable bool select_on_container_copy_construction_called_;
76    bool construct_called_;
77
78    public:
79    typedef T value_type;
80    typedef SimpleSmartPtr<T>                    pointer;
81    typedef SimpleSmartPtr<const T>              const_pointer;
82    typedef typename boost::container::
83       container_detail::unvoid<T>::type &       reference;
84    typedef const typename boost::container::
85       container_detail::unvoid<T>::type &       const_reference;
86    typedef SimpleSmartPtr<void>                 void_pointer;
87    typedef SimpleSmartPtr<const void>           const_void_pointer;
88    typedef signed short                         difference_type;
89    typedef unsigned short                       size_type;
90    typedef boost::true_type                     propagate_on_container_copy_assignment;
91    typedef boost::true_type                     propagate_on_container_move_assignment;
92    typedef boost::true_type                     propagate_on_container_swap;
93
94    ComplexAllocator()
95       : allocate_called_(false)
96       , deallocate_called_(false)
97       , allocate_hint_called_(false)
98       , destroy_called_(false)
99       , max_size_called_(false)
100       , select_on_container_copy_construction_called_(false)
101       , construct_called_(false)
102    {}
103
104    pointer allocate(size_type)
105    {  allocate_called_ = true; return pointer();  }
106
107    void deallocate(pointer, size_type)
108    {  deallocate_called_ = true;  }
109
110    //optional
111    ComplexAllocator select_on_container_copy_construction() const
112    {  select_on_container_copy_construction_called_ = true; return *this;  }
113
114    pointer allocate(size_type n, const const_void_pointer &)
115    {  allocate_hint_called_ = true; return allocate(n);  }
116
117    template<class U>
118    void destroy(U*)
119    {  destroy_called_ = true;  }
120
121    size_type max_size() const
122    {  max_size_called_ = true; return size_type(size_type(0)-1);  }
123
124    #define BOOST_PP_LOCAL_MACRO(n)                                                              \
125    template<class U  BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) >                                \
126    void construct(U *p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _))             \
127    {                                                                                            \
128       construct_called_ = true;                                                                 \
129       ::new (p) U (BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _));                      \
130    }                                                                                            \
131    //
132    #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
133    #include BOOST_PP_LOCAL_ITERATE()
134
135    //getters
136    bool allocate_called() const
137    {  return allocate_called_;  }
138
139    bool deallocate_called() const
140    {  return deallocate_called_;  }
141
142    bool allocate_hint_called() const
143    {  return allocate_hint_called_;  }
144
145    bool destroy_called() const
146    {  return destroy_called_;  }
147
148    bool max_size_called() const
149    {  return max_size_called_;  }
150
151    bool select_on_container_copy_construction_called() const
152    {  return select_on_container_copy_construction_called_;  }
153
154    bool construct_called() const
155    {  return construct_called_;  }
156 };
157
158 class copymovable
159 {
160    bool copymoveconstructed_;
161    bool moved_;
162
163    BOOST_COPYABLE_AND_MOVABLE(copymovable)
164
165    public:
166
167    copymovable(int, int, int)
168       : copymoveconstructed_(false), moved_(false)
169    {}
170
171    copymovable()
172       : copymoveconstructed_(false), moved_(false)
173    {}
174
175    copymovable(const copymovable &)
176       : copymoveconstructed_(true), moved_(false)
177    {}
178
179    copymovable(BOOST_RV_REF(copymovable))
180       : copymoveconstructed_(true), moved_(true)
181    {}
182
183    copymovable & operator=(BOOST_COPY_ASSIGN_REF(copymovable) ){ return *this; }
184    copymovable & operator=(BOOST_RV_REF(copymovable) ){ return *this; }
185
186    bool copymoveconstructed() const
187    {  return copymoveconstructed_;  }
188
189    bool moved() const
190    {  return moved_;  }
191 };
192
193 void test_void_allocator()
194 {
195    boost::container::allocator_traits<std::allocator<void>   > stdtraits; (void)stdtraits;
196    boost::container::allocator_traits<SimpleAllocator<void>  > simtraits; (void)simtraits;
197    boost::container::allocator_traits<ComplexAllocator<void> > comtraits; (void)comtraits;
198 }
199
200 int main()
201 {
202    test_void_allocator();
203
204    //SimpleAllocator
205    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
206                        < SimpleAllocator<int> >::value_type, int>::value ));
207    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
208                        < SimpleAllocator<int> >::pointer, int*>::value ));
209    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
210                        < SimpleAllocator<int> >::const_pointer, const int*>::value ));
211    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
212                        < SimpleAllocator<int> >::void_pointer, void*>::value ));
213    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
214                        < SimpleAllocator<int> >::const_void_pointer, const void*>::value ));
215    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
216                        < SimpleAllocator<int> >::difference_type, std::ptrdiff_t>::value ));
217    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
218                        < SimpleAllocator<int> >::size_type, std::size_t>::value ));
219    BOOST_STATIC_ASSERT(( boost::container::allocator_traits
220                        < SimpleAllocator<int> >::propagate_on_container_copy_assignment::value == false ));
221    BOOST_STATIC_ASSERT(( boost::container::allocator_traits
222                        < SimpleAllocator<int> >::propagate_on_container_move_assignment::value == false ));
223    BOOST_STATIC_ASSERT(( boost::container::allocator_traits
224                        < SimpleAllocator<int> >::propagate_on_container_swap::value == false ));
225    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
226                        < SimpleAllocator<int> >::rebind_traits<double>::allocator_type
227                        , SimpleAllocator<double> >::value ));
228    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
229                        < SimpleAllocator<int> >::rebind_alloc<double>::value_type
230                        , double >::value ));
231
232    //ComplexAllocator
233    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
234                        < ComplexAllocator<int> >::value_type, int>::value ));
235    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
236                        < ComplexAllocator<int> >::pointer,  SimpleSmartPtr<int> >::value ));
237    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
238                        < ComplexAllocator<int> >::const_pointer, SimpleSmartPtr<const int> >::value ));
239    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
240                        < ComplexAllocator<int> >::void_pointer, SimpleSmartPtr<void> >::value ));
241    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
242                        < ComplexAllocator<int> >::const_void_pointer, SimpleSmartPtr<const void> >::value ));
243    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
244                        < ComplexAllocator<int> >::difference_type, signed short>::value ));
245    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
246                        < ComplexAllocator<int> >::size_type, unsigned short>::value ));
247    BOOST_STATIC_ASSERT(( boost::container::allocator_traits
248                        < ComplexAllocator<int> >::propagate_on_container_copy_assignment::value == true ));
249    BOOST_STATIC_ASSERT(( boost::container::allocator_traits
250                        < ComplexAllocator<int> >::propagate_on_container_move_assignment::value == true ));
251    BOOST_STATIC_ASSERT(( boost::container::allocator_traits
252                        < ComplexAllocator<int> >::propagate_on_container_swap::value == true ));
253    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
254                        < ComplexAllocator<int> >::rebind_traits<double>::allocator_type
255                        , ComplexAllocator<double> >::value ));
256    BOOST_STATIC_ASSERT(( boost::is_same<boost::container::allocator_traits
257                        < ComplexAllocator<int> >::rebind_alloc<double>::value_type
258                        , double >::value ));
259
260    typedef ComplexAllocator<int> CAlloc;
261    typedef SimpleAllocator<int> SAlloc;
262    typedef boost::container::allocator_traits<CAlloc> CAllocTraits;
263    typedef boost::container::allocator_traits<SAlloc> SAllocTraits;
264    CAlloc c_alloc;
265    SAlloc s_alloc;
266
267    //allocate
268    CAllocTraits::allocate(c_alloc, 1);
269    if(!c_alloc.allocate_called()){
270       return 1;
271    }
272    SAllocTraits::allocate(s_alloc, 1);
273    if(!s_alloc.allocate_called()){
274       return 1;
275    }
276
277    //deallocate
278    CAllocTraits::deallocate(c_alloc, CAllocTraits::pointer(), 1);
279    if(!c_alloc.deallocate_called()){
280       return 1;
281    }
282    SAllocTraits::deallocate(s_alloc, SAllocTraits::pointer(), 1);
283    if(!s_alloc.deallocate_called()){
284       return 1;
285    }
286
287    //allocate with hint
288    CAllocTraits::allocate(c_alloc, 1, CAllocTraits::const_void_pointer());
289    if(!c_alloc.allocate_hint_called()){
290       return 1;
291    }
292    SAllocTraits::allocate(s_alloc, 1, SAllocTraits::const_void_pointer());
293
294    //destroy
295    float dummy;
296    CAllocTraits::destroy(c_alloc, &dummy);
297    if(!c_alloc.destroy_called()){
298       return 1;
299    }
300    SAllocTraits::destroy(s_alloc, &dummy);
301
302    //max_size
303    CAllocTraits::max_size(c_alloc);
304    if(!c_alloc.max_size_called()){
305       return 1;
306    }
307    SAllocTraits::max_size(s_alloc);
308
309    //select_on_container_copy_construction
310    CAllocTraits::select_on_container_copy_construction(c_alloc);
311    if(!c_alloc.select_on_container_copy_construction_called()){
312       return 1;
313    }
314    SAllocTraits::select_on_container_copy_construction(s_alloc);
315
316    //construct
317    {
318       copymovable c;
319       copymovable c2;
320       CAllocTraits::construct(c_alloc, &c, c2);
321       if(!c_alloc.construct_called() || !c.copymoveconstructed() || c.moved()){
322          return 1;
323       }
324    }
325    {
326       copymovable c;
327       copymovable c2;
328       CAllocTraits::construct(c_alloc, &c, ::boost::move(c2));
329       if(!c_alloc.construct_called() || !c.copymoveconstructed() || !c.moved()){
330          return 1;
331       }
332    }
333    {
334       copymovable c;
335       copymovable c2;
336       SAllocTraits::construct(s_alloc, &c, c2);
337       if(!c.copymoveconstructed() || c.moved()){
338          return 1;
339       }
340    }
341    {
342       copymovable c;
343       copymovable c2;
344       SAllocTraits::construct(s_alloc, &c, ::boost::move(c2));
345       if(!c.copymoveconstructed() || !c.moved()){
346          return 1;
347       }
348    }
349    {
350       copymovable c;
351       CAllocTraits::construct(c_alloc, &c, 0, 1, 2);
352       if(!c_alloc.construct_called() || c.copymoveconstructed() || c.moved()){
353          return 1;
354       }
355    }
356    {
357       copymovable c;
358       copymovable c2;
359       SAllocTraits::construct(s_alloc, &c, 0, 1, 2);
360       if(c.copymoveconstructed() || c.moved()){
361          return 1;
362       }
363    }
364
365    return 0;
366 }
367 #include <boost/container/detail/config_end.hpp>