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