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