• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2003-2013 Joaquin M Lopez Munoz.
2  * Distributed under the Boost Software License, Version 1.0.
3  * (See accompanying file LICENSE_1_0.txt or copy at
4  * http://www.boost.org/LICENSE_1_0.txt)
5  *
6  * See Boost website at http://www.boost.org/
7  */
8 
9 #ifndef BOOST_DETAIL_ALLOCATOR_UTILITIES_HPP
10 #define BOOST_DETAIL_ALLOCATOR_UTILITIES_HPP
11 
12 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
13 #include <boost/detail/workaround.hpp>
14 #include <boost/detail/select_type.hpp>
15 #include <boost/type_traits/is_same.hpp>
16 #include <cstddef>
17 #include <memory>
18 #include <new>
19 
20 namespace boost{
21 
22 namespace detail{
23 
24 /* Allocator adaption layer. Some stdlibs provide allocators without rebind
25  * and template ctors. These facilities are simulated with the external
26  * template class rebind_to and the aid of partial_std_allocator_wrapper.
27  */
28 
29 namespace allocator{
30 
31 /* partial_std_allocator_wrapper inherits the functionality of a std
32  * allocator while providing a templatized ctor and other bits missing
33  * in some stdlib implementation or another.
34  */
35 
36 template<typename Type>
37 class partial_std_allocator_wrapper:public std::allocator<Type>
38 {
39 public:
40   /* Oddly enough, STLport does not define std::allocator<void>::value_type
41    * when configured to work without partial template specialization.
42    * No harm in supplying the definition here unconditionally.
43    */
44 
45   typedef Type value_type;
46 
partial_std_allocator_wrapper()47   partial_std_allocator_wrapper(){}
48 
49   template<typename Other>
partial_std_allocator_wrapper(const partial_std_allocator_wrapper<Other> &)50   partial_std_allocator_wrapper(const partial_std_allocator_wrapper<Other>&){}
51 
partial_std_allocator_wrapper(const std::allocator<Type> & x)52   partial_std_allocator_wrapper(const std::allocator<Type>& x):
53     std::allocator<Type>(x)
54   {
55   }
56 
57 #if defined(BOOST_DINKUMWARE_STDLIB)
58   /* Dinkumware guys didn't provide a means to call allocate() without
59    * supplying a hint, in disagreement with the standard.
60    */
61 
allocate(std::size_t n,const void * hint=0)62   Type* allocate(std::size_t n,const void* hint=0)
63   {
64     std::allocator<Type>& a=*this;
65     return a.allocate(n,hint);
66   }
67 #endif
68 
69 };
70 
71 /* Detects whether a given allocator belongs to a defective stdlib not
72  * having the required member templates.
73  * Note that it does not suffice to check the Boost.Config stdlib
74  * macros, as the user might have passed a custom, compliant allocator.
75  * The checks also considers partial_std_allocator_wrapper to be
76  * a standard defective allocator.
77  */
78 
79 #if defined(BOOST_NO_STD_ALLOCATOR)&&\
80   (defined(BOOST_HAS_PARTIAL_STD_ALLOCATOR)||defined(BOOST_DINKUMWARE_STDLIB))
81 
82 template<typename Allocator>
83 struct is_partial_std_allocator
84 {
85   BOOST_STATIC_CONSTANT(bool,
86     value=
87       (is_same<
88         std::allocator<BOOST_DEDUCED_TYPENAME Allocator::value_type>,
89         Allocator
90       >::value)||
91       (is_same<
92         partial_std_allocator_wrapper<
93           BOOST_DEDUCED_TYPENAME Allocator::value_type>,
94         Allocator
95       >::value));
96 };
97 
98 #else
99 
100 template<typename Allocator>
101 struct is_partial_std_allocator
102 {
103   BOOST_STATIC_CONSTANT(bool,value=false);
104 };
105 
106 #endif
107 
108 /* rebind operations for defective std allocators */
109 
110 template<typename Allocator,typename Type>
111 struct partial_std_allocator_rebind_to
112 {
113   typedef partial_std_allocator_wrapper<Type> type;
114 };
115 
116 /* rebind operation in all other cases */
117 
118 template<typename Allocator>
119 struct rebinder
120 {
121   template<typename Type>
122   struct result
123   {
124 #ifdef BOOST_NO_CXX11_ALLOCATOR
125       typedef typename Allocator::BOOST_NESTED_TEMPLATE
126           rebind<Type>::other other;
127 #else
128       typedef typename std::allocator_traits<Allocator>::BOOST_NESTED_TEMPLATE
129           rebind_alloc<Type> other;
130 #endif
131   };
132 };
133 
134 template<typename Allocator,typename Type>
135 struct compliant_allocator_rebind_to
136 {
137   typedef typename rebinder<Allocator>::
138       BOOST_NESTED_TEMPLATE result<Type>::other type;
139 };
140 
141 /* rebind front-end */
142 
143 template<typename Allocator,typename Type>
144 struct rebind_to:
145   boost::detail::if_true<
146     is_partial_std_allocator<Allocator>::value
147   >::template then<
148     partial_std_allocator_rebind_to<Allocator,Type>,
149     compliant_allocator_rebind_to<Allocator,Type>
150   >::type
151 {
152 };
153 
154 /* allocator-independent versions of construct and destroy */
155 
156 template<typename Type>
construct(void * p,const Type & t)157 void construct(void* p,const Type& t)
158 {
159   new (p) Type(t);
160 }
161 
162 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
163 /* MSVC++ issues spurious warnings about unreferencend formal parameters
164  * in destroy<Type> when Type is a class with trivial dtor.
165  */
166 
167 #pragma warning(push)
168 #pragma warning(disable:4100)
169 #endif
170 
171 template<typename Type>
destroy(const Type * p)172 void destroy(const Type* p)
173 {
174 
175 #if BOOST_WORKAROUND(__SUNPRO_CC,BOOST_TESTED_AT(0x590))
176   const_cast<Type*>(p)->~Type();
177 #else
178   p->~Type();
179 #endif
180 
181 }
182 
183 #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500))
184 #pragma warning(pop)
185 #endif
186 
187 } /* namespace boost::detail::allocator */
188 
189 } /* namespace boost::detail */
190 
191 } /* namespace boost */
192 
193 #endif
194