]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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/mpl/eval_if.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 | ||
47 | partial_std_allocator_wrapper(){}; | |
48 | ||
49 | template<typename Other> | |
50 | partial_std_allocator_wrapper(const partial_std_allocator_wrapper<Other>&){} | |
51 | ||
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 | ||
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 | typedef typename Allocator::BOOST_NESTED_TEMPLATE | |
125 | rebind<Type>::other other; | |
126 | }; | |
127 | }; | |
128 | ||
129 | template<typename Allocator,typename Type> | |
130 | struct compliant_allocator_rebind_to | |
131 | { | |
132 | typedef typename rebinder<Allocator>:: | |
133 | BOOST_NESTED_TEMPLATE result<Type>::other type; | |
134 | }; | |
135 | ||
136 | /* rebind front-end */ | |
137 | ||
138 | template<typename Allocator,typename Type> | |
139 | struct rebind_to: | |
140 | mpl::eval_if_c< | |
141 | is_partial_std_allocator<Allocator>::value, | |
142 | partial_std_allocator_rebind_to<Allocator,Type>, | |
143 | compliant_allocator_rebind_to<Allocator,Type> | |
144 | > | |
145 | { | |
146 | }; | |
147 | ||
148 | /* allocator-independent versions of construct and destroy */ | |
149 | ||
150 | template<typename Type> | |
151 | void construct(void* p,const Type& t) | |
152 | { | |
153 | new (p) Type(t); | |
154 | } | |
155 | ||
156 | #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500)) | |
157 | /* MSVC++ issues spurious warnings about unreferencend formal parameters | |
158 | * in destroy<Type> when Type is a class with trivial dtor. | |
159 | */ | |
160 | ||
161 | #pragma warning(push) | |
162 | #pragma warning(disable:4100) | |
163 | #endif | |
164 | ||
165 | template<typename Type> | |
166 | void destroy(const Type* p) | |
167 | { | |
168 | ||
169 | #if BOOST_WORKAROUND(__SUNPRO_CC,BOOST_TESTED_AT(0x590)) | |
170 | const_cast<Type*>(p)->~Type(); | |
171 | #else | |
172 | p->~Type(); | |
173 | #endif | |
174 | ||
175 | } | |
176 | ||
177 | #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1500)) | |
178 | #pragma warning(pop) | |
179 | #endif | |
180 | ||
181 | } /* namespace boost::detail::allocator */ | |
182 | ||
183 | } /* namespace boost::detail */ | |
184 | ||
185 | } /* namespace boost */ | |
186 | ||
187 | #endif |