1 | // (C) Copyright 2002-2008, Fernando Luis Cacciola Carballal. |
2 | // |
3 | // Distributed under the Boost Software License, Version 1.0. (See |
4 | // accompanying file LICENSE_1_0.txt or copy at |
5 | // http://www.boost.org/LICENSE_1_0.txt) |
6 | // |
7 | // 21 Ago 2002 (Created) Fernando Cacciola |
8 | // 24 Dec 2007 (Refactored and worked around various compiler bugs) Fernando Cacciola, Niels Dekker |
9 | // 23 May 2008 (Fixed operator= const issue, added initialized_value) Niels Dekker, Fernando Cacciola |
10 | // 21 Ago 2008 (Added swap) Niels Dekker, Fernando Cacciola |
11 | // 20 Feb 2009 (Fixed logical const-ness issues) Niels Dekker, Fernando Cacciola |
12 | // 03 Apr 2010 (Added initialized<T>, suggested by Jeffrey Hellrung, fixing #3472) Niels Dekker |
13 | // 30 May 2010 (Made memset call conditional, fixing #3869) Niels Dekker |
14 | // |
15 | #ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP |
16 | #define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP |
17 | |
18 | // Note: The implementation of boost::value_initialized had to deal with the |
19 | // fact that various compilers haven't fully implemented value-initialization. |
20 | // The constructor of boost::value_initialized<T> works around these compiler |
21 | // issues, by clearing the bytes of T, before constructing the T object it |
22 | // contains. More details on these issues are at libs/utility/value_init.htm |
23 | |
24 | #include <boost/aligned_storage.hpp> |
25 | #include <boost/config.hpp> // For BOOST_NO_COMPLETE_VALUE_INITIALIZATION. |
26 | #include <boost/detail/workaround.hpp> |
27 | #include <boost/static_assert.hpp> |
28 | #include <boost/type_traits/cv_traits.hpp> |
29 | #include <boost/type_traits/alignment_of.hpp> |
30 | #include <boost/swap.hpp> |
31 | #include <cstring> |
32 | #include <new> |
33 | |
34 | #ifdef BOOST_MSVC |
35 | #pragma warning(push) |
36 | // It is safe to ignore the following warning from MSVC 7.1 or higher: |
37 | // "warning C4351: new behavior: elements of array will be default initialized" |
38 | #pragma warning(disable: 4351) |
39 | // It is safe to ignore the following MSVC warning, which may pop up when T is |
40 | // a const type: "warning C4512: assignment operator could not be generated". |
41 | #pragma warning(disable: 4512) |
42 | #endif |
43 | |
44 | #ifdef BOOST_NO_COMPLETE_VALUE_INITIALIZATION |
45 | // Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED |
46 | // suggests that a workaround should be applied, because of compiler issues |
47 | // regarding value-initialization. |
48 | #define BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED |
49 | #endif |
50 | |
51 | // Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND |
52 | // switches the value-initialization workaround either on or off. |
53 | #ifndef BOOST_DETAIL_VALUE_INIT_WORKAROUND |
54 | #ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED |
55 | #define BOOST_DETAIL_VALUE_INIT_WORKAROUND 1 |
56 | #else |
57 | #define BOOST_DETAIL_VALUE_INIT_WORKAROUND 0 |
58 | #endif |
59 | #endif |
60 | |
61 | namespace boost { |
62 | |
63 | template<class T> |
64 | class initialized |
65 | { |
66 | private : |
67 | struct wrapper |
68 | { |
69 | #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) |
70 | typename |
71 | #endif |
72 | remove_const<T>::type data; |
73 | |
74 | BOOST_GPU_ENABLED |
75 | wrapper() |
76 | : |
77 | data() |
78 | { |
79 | } |
80 | |
81 | BOOST_GPU_ENABLED |
82 | wrapper(T const & arg) |
83 | : |
84 | data(arg) |
85 | { |
86 | } |
87 | }; |
88 | |
89 | mutable |
90 | #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) |
91 | typename |
92 | #endif |
93 | aligned_storage<sizeof(wrapper), alignment_of<wrapper>::value>::type x; |
94 | |
95 | BOOST_GPU_ENABLED |
96 | wrapper * wrapper_address() const |
97 | { |
98 | return static_cast<wrapper *>( static_cast<void*>(&x)); |
99 | } |
100 | |
101 | public : |
102 | |
103 | BOOST_GPU_ENABLED |
104 | initialized() |
105 | { |
106 | #if BOOST_DETAIL_VALUE_INIT_WORKAROUND |
107 | std::memset(&x, 0, sizeof(x)); |
108 | #endif |
109 | new (wrapper_address()) wrapper(); |
110 | } |
111 | |
112 | BOOST_GPU_ENABLED |
113 | initialized(initialized const & arg) |
114 | { |
115 | new (wrapper_address()) wrapper( static_cast<wrapper const &>(*(arg.wrapper_address()))); |
116 | } |
117 | |
118 | BOOST_GPU_ENABLED |
119 | explicit initialized(T const & arg) |
120 | { |
121 | new (wrapper_address()) wrapper(arg); |
122 | } |
123 | |
124 | BOOST_GPU_ENABLED |
125 | initialized & operator=(initialized const & arg) |
126 | { |
127 | // Assignment is only allowed when T is non-const. |
128 | BOOST_STATIC_ASSERT( ! is_const<T>::value ); |
129 | *wrapper_address() = static_cast<wrapper const &>(*(arg.wrapper_address())); |
130 | return *this; |
131 | } |
132 | |
133 | BOOST_GPU_ENABLED |
134 | ~initialized() |
135 | { |
136 | wrapper_address()->wrapper::~wrapper(); |
137 | } |
138 | |
139 | BOOST_GPU_ENABLED |
140 | T const & data() const |
141 | { |
142 | return wrapper_address()->data; |
143 | } |
144 | |
145 | BOOST_GPU_ENABLED |
146 | T& data() |
147 | { |
148 | return wrapper_address()->data; |
149 | } |
150 | |
151 | BOOST_GPU_ENABLED |
152 | void swap(initialized & arg) |
153 | { |
154 | ::boost::swap( this->data(), arg.data() ); |
155 | } |
156 | |
157 | BOOST_GPU_ENABLED |
158 | operator T const &() const |
159 | { |
160 | return wrapper_address()->data; |
161 | } |
162 | |
163 | BOOST_GPU_ENABLED |
164 | operator T&() |
165 | { |
166 | return wrapper_address()->data; |
167 | } |
168 | |
169 | } ; |
170 | |
171 | template<class T> |
172 | BOOST_GPU_ENABLED |
173 | T const& get ( initialized<T> const& x ) |
174 | { |
175 | return x.data() ; |
176 | } |
177 | |
178 | template<class T> |
179 | BOOST_GPU_ENABLED |
180 | T& get ( initialized<T>& x ) |
181 | { |
182 | return x.data() ; |
183 | } |
184 | |
185 | template<class T> |
186 | BOOST_GPU_ENABLED |
187 | void swap ( initialized<T> & lhs, initialized<T> & rhs ) |
188 | { |
189 | lhs.swap(rhs) ; |
190 | } |
191 | |
192 | template<class T> |
193 | class value_initialized |
194 | { |
195 | private : |
196 | |
197 | // initialized<T> does value-initialization by default. |
198 | initialized<T> m_data; |
199 | |
200 | public : |
201 | |
202 | BOOST_GPU_ENABLED |
203 | value_initialized() |
204 | : |
205 | m_data() |
206 | { } |
207 | |
208 | BOOST_GPU_ENABLED |
209 | T const & data() const |
210 | { |
211 | return m_data.data(); |
212 | } |
213 | |
214 | BOOST_GPU_ENABLED |
215 | T& data() |
216 | { |
217 | return m_data.data(); |
218 | } |
219 | |
220 | BOOST_GPU_ENABLED |
221 | void swap(value_initialized & arg) |
222 | { |
223 | m_data.swap(arg.m_data); |
224 | } |
225 | |
226 | BOOST_GPU_ENABLED |
227 | operator T const &() const |
228 | { |
229 | return m_data; |
230 | } |
231 | |
232 | BOOST_GPU_ENABLED |
233 | operator T&() |
234 | { |
235 | return m_data; |
236 | } |
237 | } ; |
238 | |
239 | |
240 | template<class T> |
241 | BOOST_GPU_ENABLED |
242 | T const& get ( value_initialized<T> const& x ) |
243 | { |
244 | return x.data() ; |
245 | } |
246 | |
247 | template<class T> |
248 | BOOST_GPU_ENABLED |
249 | T& get ( value_initialized<T>& x ) |
250 | { |
251 | return x.data() ; |
252 | } |
253 | |
254 | template<class T> |
255 | BOOST_GPU_ENABLED |
256 | void swap ( value_initialized<T> & lhs, value_initialized<T> & rhs ) |
257 | { |
258 | lhs.swap(rhs) ; |
259 | } |
260 | |
261 | |
262 | class initialized_value_t |
263 | { |
264 | public : |
265 | |
266 | template <class T> BOOST_GPU_ENABLED operator T() const |
267 | { |
268 | return initialized<T>().data(); |
269 | } |
270 | }; |
271 | |
272 | initialized_value_t const initialized_value = {} ; |
273 | |
274 | |
275 | } // namespace boost |
276 | |
277 | #ifdef BOOST_MSVC |
278 | #pragma warning(pop) |
279 | #endif |
280 | |
281 | #endif |
282 | |