Merge c:/dyninst/pc_bluegene/dyninst into dyn_pc_integration
[dyninst.git] / external / boost / detail / allocator_utilities.hpp
1 /* Copyright 2003-2008 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/mpl/aux_/msvc_never_true.hpp>
15 #include <boost/mpl/eval_if.hpp>
16 #include <boost/type_traits/is_same.hpp>
17 #include <cstddef>
18 #include <memory>
19 #include <new>
20
21 namespace boost{
22
23 namespace detail{
24
25 /* Allocator adaption layer. Some stdlibs provide allocators without rebind
26  * and template ctors. These facilities are simulated with the external
27  * template class rebind_to and the aid of partial_std_allocator_wrapper.
28  */
29
30 namespace allocator{
31
32 /* partial_std_allocator_wrapper inherits the functionality of a std
33  * allocator while providing a templatized ctor and other bits missing
34  * in some stdlib implementation or another.
35  */
36
37 template<typename Type>
38 class partial_std_allocator_wrapper:public std::allocator<Type>
39 {
40 public:
41   /* Oddly enough, STLport does not define std::allocator<void>::value_type
42    * when configured to work without partial template specialization.
43    * No harm in supplying the definition here unconditionally.
44    */
45
46   typedef Type value_type;
47
48   partial_std_allocator_wrapper(){};
49
50   template<typename Other>
51   partial_std_allocator_wrapper(const partial_std_allocator_wrapper<Other>&){}
52
53   partial_std_allocator_wrapper(const std::allocator<Type>& x):
54     std::allocator<Type>(x)
55   {
56   };
57
58 #if defined(BOOST_DINKUMWARE_STDLIB)
59   /* Dinkumware guys didn't provide a means to call allocate() without
60    * supplying a hint, in disagreement with the standard.
61    */
62
63   Type* allocate(std::size_t n,const void* hint=0)
64   {
65     std::allocator<Type>& a=*this;
66     return a.allocate(n,hint);
67   }
68 #endif
69
70 };
71
72 /* Detects whether a given allocator belongs to a defective stdlib not
73  * having the required member templates.
74  * Note that it does not suffice to check the Boost.Config stdlib
75  * macros, as the user might have passed a custom, compliant allocator.
76  * The checks also considers partial_std_allocator_wrapper to be
77  * a standard defective allocator.
78  */
79
80 #if defined(BOOST_NO_STD_ALLOCATOR)&&\
81   (defined(BOOST_HAS_PARTIAL_STD_ALLOCATOR)||defined(BOOST_DINKUMWARE_STDLIB))
82
83 template<typename Allocator>
84 struct is_partial_std_allocator
85 {
86   BOOST_STATIC_CONSTANT(bool,
87     value=
88       (is_same<
89         std::allocator<BOOST_DEDUCED_TYPENAME Allocator::value_type>,
90         Allocator
91       >::value)||
92       (is_same<
93         partial_std_allocator_wrapper<
94           BOOST_DEDUCED_TYPENAME Allocator::value_type>,
95         Allocator
96       >::value));
97 };
98
99 #else
100
101 template<typename Allocator>
102 struct is_partial_std_allocator
103 {
104   BOOST_STATIC_CONSTANT(bool,value=false);
105 };
106
107 #endif
108
109 /* rebind operations for defective std allocators */
110
111 template<typename Allocator,typename Type>
112 struct partial_std_allocator_rebind_to
113 {
114   typedef partial_std_allocator_wrapper<Type> type;
115 };
116
117 /* rebind operation in all other cases */
118
119 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
120 /* Workaround for a problem in MSVC with dependent template typedefs
121  * when doing rebinding of allocators.
122  * Modeled after <boost/mpl/aux_/msvc_dtw.hpp> (thanks, Aleksey!)
123  */
124
125 template<typename Allocator>
126 struct rebinder
127 {
128   template<bool> struct fake_allocator:Allocator{};
129   template<> struct fake_allocator<true>
130   {
131     template<typename Type> struct rebind{};
132   };
133
134   template<typename Type>
135   struct result:
136     fake_allocator<mpl::aux::msvc_never_true<Allocator>::value>::
137       template rebind<Type>
138   {
139   };
140 };
141 #else
142 template<typename Allocator>
143 struct rebinder
144 {
145   template<typename Type>
146   struct result
147   {
148       typedef typename Allocator::BOOST_NESTED_TEMPLATE 
149           rebind<Type>::other other;
150   };
151 };
152 #endif
153
154 template<typename Allocator,typename Type>
155 struct compliant_allocator_rebind_to
156 {
157   typedef typename rebinder<Allocator>::
158       BOOST_NESTED_TEMPLATE result<Type>::other type;
159 };
160
161 /* rebind front-end */
162
163 template<typename Allocator,typename Type>
164 struct rebind_to:
165   mpl::eval_if_c<
166     is_partial_std_allocator<Allocator>::value,
167     partial_std_allocator_rebind_to<Allocator,Type>,
168     compliant_allocator_rebind_to<Allocator,Type>
169   >
170 {
171 };
172
173 /* allocator-independent versions of construct and destroy */
174
175 template<typename Type>
176 void construct(void* p,const Type& t)
177 {
178   new (p) Type(t);
179 }
180
181 template<typename Type>
182 void destroy(const Type* p)
183 {
184   p->~Type();
185 }
186
187 } /* namespace boost::detail::allocator */
188
189 } /* namespace boost::detail */
190
191 } /* namespace boost */
192
193 #endif