Imported Upstream version 0.8~alpha1
[platform/upstream/syncevolution.git] / src / boost / detail / allocator_utilities.hpp
1 /* Copyright 2003-2005 Joaquín M López Muñoz.
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.
34  */
35
36 template<typename Type>
37 class partial_std_allocator_wrapper:public std::allocator<Type>
38 {
39 public:
40   partial_std_allocator_wrapper(){};
41
42   template<typename Other>
43   partial_std_allocator_wrapper(const partial_std_allocator_wrapper<Other>&){}
44
45   partial_std_allocator_wrapper(const std::allocator<Type>& x):
46     std::allocator<Type>(x)
47   {
48   };
49
50 #if defined(BOOST_DINKUMWARE_STDLIB)
51   /* Dinkumware guys didn't provide a means to call allocate() without
52    * supplying a hint, in disagreement with the standard.
53    */
54
55   Type* allocate(std::size_t n,const void* hint=0)
56   {
57     std::allocator<Type>& a=*this;
58     return a.allocate(n,hint);
59   }
60 #endif
61
62 };
63
64 /* Detects whether a given allocator belongs to a defective stdlib not
65  * having the required member templates.
66  * Note that it does not suffice to check the Boost.Config stdlib
67  * macros, as the user might have passed a custom, compliant allocator.
68  * The checks also considers partial_std_allocator_wrapper to be
69  * a standard defective allocator.
70  */
71
72 #if defined(BOOST_NO_STD_ALLOCATOR)&&\
73   (defined(BOOST_HAS_PARTIAL_STD_ALLOCATOR)||defined(BOOST_DINKUMWARE_STDLIB))
74
75 template<typename Allocator>
76 struct is_partial_std_allocator
77 {
78   BOOST_STATIC_CONSTANT(bool,
79     value=
80       (is_same<
81         std::allocator<BOOST_DEDUCED_TYPENAME Allocator::value_type>,
82         Allocator
83       >::value)||
84       (is_same<
85         partial_std_allocator_wrapper<
86           BOOST_DEDUCED_TYPENAME Allocator::value_type>,
87         Allocator
88       >::value));
89 };
90
91 #else
92
93 template<typename Allocator>
94 struct is_partial_std_allocator
95 {
96   BOOST_STATIC_CONSTANT(bool,value=false);
97 };
98
99 #endif
100
101 /* rebind operations for defective std allocators */
102
103 template<typename Allocator,typename Type>
104 struct partial_std_allocator_rebind_to
105 {
106   typedef partial_std_allocator_wrapper<Type> type;
107 };
108
109 /* rebind operation in all other cases */
110
111 #if BOOST_WORKAROUND(BOOST_MSVC,<1300)
112 /* Workaround for a problem in MSVC with dependent template typedefs
113  * when doing rebinding of allocators.
114  * Modeled after <boost/mpl/aux_/msvc_dtw.hpp> (thanks, Aleksey!)
115  */
116
117 template<typename Allocator>
118 struct rebinder
119 {
120   template<bool> struct fake_allocator:Allocator{};
121   template<> struct fake_allocator<true>
122   {
123     template<typename Type> struct rebind{};
124   };
125
126   template<typename Type>
127   struct result:
128     fake_allocator<mpl::aux::msvc_never_true<Allocator>::value>::
129       template rebind<Type>
130   {
131   };
132 };
133 #else
134 template<typename Allocator>
135 struct rebinder
136 {
137   template<typename Type>
138   struct result
139   {
140       typedef typename Allocator::BOOST_NESTED_TEMPLATE 
141           rebind<Type>::other other;
142   };
143 };
144 #endif
145
146 template<typename Allocator,typename Type>
147 struct compliant_allocator_rebind_to
148 {
149   typedef typename rebinder<Allocator>::
150       BOOST_NESTED_TEMPLATE result<Type>::other type;
151 };
152
153 /* rebind front-end */
154
155 template<typename Allocator,typename Type>
156 struct rebind_to:
157   mpl::eval_if_c<
158     is_partial_std_allocator<Allocator>::value,
159     partial_std_allocator_rebind_to<Allocator,Type>,
160     compliant_allocator_rebind_to<Allocator,Type>
161   >
162 {
163 };
164
165 /* allocator-independent versions of construct and destroy */
166
167 template<typename Type>
168 void construct(void* p,const Type& t)
169 {
170   new (p) Type(t);
171 }
172
173 template<typename Type>
174 void destroy(const Type* p)
175 {
176   p->~Type();
177 }
178
179 } /* namespace boost::detail::allocator */
180
181 } /* namespace boost::detail */
182
183 } /* namespace boost */
184
185 #endif