value_init.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  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. // Note: The implementation of boost::value_initialized had to deal with the
  18. // fact that various compilers haven't fully implemented value-initialization.
  19. // The constructor of boost::value_initialized<T> works around these compiler
  20. // issues, by clearing the bytes of T, before constructing the T object it
  21. // contains. More details on these issues are at libs/utility/value_init.htm
  22. #include <boost/aligned_storage.hpp>
  23. #include <boost/config.hpp> // For BOOST_NO_COMPLETE_VALUE_INITIALIZATION.
  24. #include <boost/detail/workaround.hpp>
  25. #include <boost/static_assert.hpp>
  26. #include <boost/type_traits/cv_traits.hpp>
  27. #include <boost/type_traits/alignment_of.hpp>
  28. #include <boost/swap.hpp>
  29. #include <cstring>
  30. #include <new>
  31. #ifdef BOOST_MSVC
  32. #pragma warning(push)
  33. // It is safe to ignore the following warning from MSVC 7.1 or higher:
  34. // "warning C4351: new behavior: elements of array will be default initialized"
  35. #pragma warning(disable: 4351)
  36. // It is safe to ignore the following MSVC warning, which may pop up when T is
  37. // a const type: "warning C4512: assignment operator could not be generated".
  38. #pragma warning(disable: 4512)
  39. #endif
  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. // Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND
  47. // switches the value-initialization workaround either on or off.
  48. #ifndef BOOST_DETAIL_VALUE_INIT_WORKAROUND
  49. #ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
  50. #define BOOST_DETAIL_VALUE_INIT_WORKAROUND 1
  51. #else
  52. #define BOOST_DETAIL_VALUE_INIT_WORKAROUND 0
  53. #endif
  54. #endif
  55. namespace boost {
  56. template<class T>
  57. class initialized
  58. {
  59. private :
  60. struct wrapper
  61. {
  62. #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
  63. typename
  64. #endif
  65. remove_const<T>::type data;
  66. BOOST_GPU_ENABLED
  67. wrapper()
  68. :
  69. data()
  70. {
  71. }
  72. BOOST_GPU_ENABLED
  73. wrapper(T const & arg)
  74. :
  75. data(arg)
  76. {
  77. }
  78. };
  79. mutable
  80. #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
  81. typename
  82. #endif
  83. aligned_storage<sizeof(wrapper), alignment_of<wrapper>::value>::type x;
  84. BOOST_GPU_ENABLED
  85. wrapper * wrapper_address() const
  86. {
  87. return static_cast<wrapper *>( static_cast<void*>(&x));
  88. }
  89. public :
  90. BOOST_GPU_ENABLED
  91. initialized()
  92. {
  93. #if BOOST_DETAIL_VALUE_INIT_WORKAROUND
  94. std::memset(&x, 0, sizeof(x));
  95. #endif
  96. new (wrapper_address()) wrapper();
  97. }
  98. BOOST_GPU_ENABLED
  99. initialized(initialized const & arg)
  100. {
  101. new (wrapper_address()) wrapper( static_cast<wrapper const &>(*(arg.wrapper_address())));
  102. }
  103. BOOST_GPU_ENABLED
  104. explicit initialized(T const & arg)
  105. {
  106. new (wrapper_address()) wrapper(arg);
  107. }
  108. BOOST_GPU_ENABLED
  109. initialized & operator=(initialized const & arg)
  110. {
  111. // Assignment is only allowed when T is non-const.
  112. BOOST_STATIC_ASSERT( ! is_const<T>::value );
  113. *wrapper_address() = static_cast<wrapper const &>(*(arg.wrapper_address()));
  114. return *this;
  115. }
  116. BOOST_GPU_ENABLED
  117. ~initialized()
  118. {
  119. wrapper_address()->wrapper::~wrapper();
  120. }
  121. BOOST_GPU_ENABLED
  122. T const & data() const
  123. {
  124. return wrapper_address()->data;
  125. }
  126. BOOST_GPU_ENABLED
  127. T& data()
  128. {
  129. return wrapper_address()->data;
  130. }
  131. BOOST_GPU_ENABLED
  132. void swap(initialized & arg)
  133. {
  134. ::boost::swap( this->data(), arg.data() );
  135. }
  136. BOOST_GPU_ENABLED
  137. operator T const &() const
  138. {
  139. return wrapper_address()->data;
  140. }
  141. BOOST_GPU_ENABLED
  142. operator T&()
  143. {
  144. return wrapper_address()->data;
  145. }
  146. } ;
  147. template<class T>
  148. BOOST_GPU_ENABLED
  149. T const& get ( initialized<T> const& x )
  150. {
  151. return x.data() ;
  152. }
  153. template<class T>
  154. BOOST_GPU_ENABLED
  155. T& get ( initialized<T>& x )
  156. {
  157. return x.data() ;
  158. }
  159. template<class T>
  160. BOOST_GPU_ENABLED
  161. void swap ( initialized<T> & lhs, initialized<T> & rhs )
  162. {
  163. lhs.swap(rhs) ;
  164. }
  165. template<class T>
  166. class value_initialized
  167. {
  168. private :
  169. // initialized<T> does value-initialization by default.
  170. initialized<T> m_data;
  171. public :
  172. BOOST_GPU_ENABLED
  173. value_initialized()
  174. :
  175. m_data()
  176. { }
  177. BOOST_GPU_ENABLED
  178. T const & data() const
  179. {
  180. return m_data.data();
  181. }
  182. BOOST_GPU_ENABLED
  183. T& data()
  184. {
  185. return m_data.data();
  186. }
  187. BOOST_GPU_ENABLED
  188. void swap(value_initialized & arg)
  189. {
  190. m_data.swap(arg.m_data);
  191. }
  192. BOOST_GPU_ENABLED
  193. operator T const &() const
  194. {
  195. return m_data;
  196. }
  197. BOOST_GPU_ENABLED
  198. operator T&()
  199. {
  200. return m_data;
  201. }
  202. } ;
  203. template<class T>
  204. BOOST_GPU_ENABLED
  205. T const& get ( value_initialized<T> const& x )
  206. {
  207. return x.data() ;
  208. }
  209. template<class T>
  210. BOOST_GPU_ENABLED
  211. T& get ( value_initialized<T>& x )
  212. {
  213. return x.data() ;
  214. }
  215. template<class T>
  216. BOOST_GPU_ENABLED
  217. void swap ( value_initialized<T> & lhs, value_initialized<T> & rhs )
  218. {
  219. lhs.swap(rhs) ;
  220. }
  221. class initialized_value_t
  222. {
  223. public :
  224. template <class T> BOOST_GPU_ENABLED operator T() const
  225. {
  226. return initialized<T>().data();
  227. }
  228. };
  229. initialized_value_t const initialized_value = {} ;
  230. } // namespace boost
  231. #ifdef BOOST_MSVC
  232. #pragma warning(pop)
  233. #endif
  234. #endif