value_init.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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. #if _MSC_VER >= 1310
  34. // It is safe to ignore the following warning from MSVC 7.1 or higher:
  35. // "warning C4351: new behavior: elements of array will be default initialized"
  36. #pragma warning(disable: 4351)
  37. // It is safe to ignore the following MSVC warning, which may pop up when T is
  38. // a const type: "warning C4512: assignment operator could not be generated".
  39. #pragma warning(disable: 4512)
  40. #endif
  41. #endif
  42. #ifdef BOOST_NO_COMPLETE_VALUE_INITIALIZATION
  43. // Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
  44. // suggests that a workaround should be applied, because of compiler issues
  45. // regarding value-initialization.
  46. #define BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
  47. #endif
  48. // Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND
  49. // switches the value-initialization workaround either on or off.
  50. #ifndef BOOST_DETAIL_VALUE_INIT_WORKAROUND
  51. #ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
  52. #define BOOST_DETAIL_VALUE_INIT_WORKAROUND 1
  53. #else
  54. #define BOOST_DETAIL_VALUE_INIT_WORKAROUND 0
  55. #endif
  56. #endif
  57. namespace boost {
  58. template<class T>
  59. class initialized
  60. {
  61. private :
  62. struct wrapper
  63. {
  64. #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592))
  65. typename
  66. #endif
  67. remove_const<T>::type data;
  68. wrapper()
  69. :
  70. data()
  71. {
  72. }
  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. wrapper * wrapper_address() const
  85. {
  86. return static_cast<wrapper *>( static_cast<void*>(&x));
  87. }
  88. public :
  89. initialized()
  90. {
  91. #if BOOST_DETAIL_VALUE_INIT_WORKAROUND
  92. std::memset(&x, 0, sizeof(x));
  93. #endif
  94. new (wrapper_address()) wrapper();
  95. }
  96. initialized(initialized const & arg)
  97. {
  98. new (wrapper_address()) wrapper( static_cast<wrapper const &>(*(arg.wrapper_address())));
  99. }
  100. explicit initialized(T const & arg)
  101. {
  102. new (wrapper_address()) wrapper(arg);
  103. }
  104. initialized & operator=(initialized const & arg)
  105. {
  106. // Assignment is only allowed when T is non-const.
  107. BOOST_STATIC_ASSERT( ! is_const<T>::value );
  108. *wrapper_address() = static_cast<wrapper const &>(*(arg.wrapper_address()));
  109. return *this;
  110. }
  111. ~initialized()
  112. {
  113. wrapper_address()->wrapper::~wrapper();
  114. }
  115. T const & data() const
  116. {
  117. return wrapper_address()->data;
  118. }
  119. T& data()
  120. {
  121. return wrapper_address()->data;
  122. }
  123. void swap(initialized & arg)
  124. {
  125. ::boost::swap( this->data(), arg.data() );
  126. }
  127. operator T const &() const
  128. {
  129. return wrapper_address()->data;
  130. }
  131. operator T&()
  132. {
  133. return wrapper_address()->data;
  134. }
  135. } ;
  136. template<class T>
  137. T const& get ( initialized<T> const& x )
  138. {
  139. return x.data() ;
  140. }
  141. template<class T>
  142. T& get ( initialized<T>& x )
  143. {
  144. return x.data() ;
  145. }
  146. template<class T>
  147. void swap ( initialized<T> & lhs, initialized<T> & rhs )
  148. {
  149. lhs.swap(rhs) ;
  150. }
  151. template<class T>
  152. class value_initialized
  153. {
  154. private :
  155. // initialized<T> does value-initialization by default.
  156. initialized<T> m_data;
  157. public :
  158. value_initialized()
  159. :
  160. m_data()
  161. { }
  162. T const & data() const
  163. {
  164. return m_data.data();
  165. }
  166. T& data()
  167. {
  168. return m_data.data();
  169. }
  170. void swap(value_initialized & arg)
  171. {
  172. m_data.swap(arg.m_data);
  173. }
  174. operator T const &() const
  175. {
  176. return m_data;
  177. }
  178. operator T&()
  179. {
  180. return m_data;
  181. }
  182. } ;
  183. template<class T>
  184. T const& get ( value_initialized<T> const& x )
  185. {
  186. return x.data() ;
  187. }
  188. template<class T>
  189. T& get ( value_initialized<T>& x )
  190. {
  191. return x.data() ;
  192. }
  193. template<class T>
  194. void swap ( value_initialized<T> & lhs, value_initialized<T> & rhs )
  195. {
  196. lhs.swap(rhs) ;
  197. }
  198. class initialized_value_t
  199. {
  200. public :
  201. template <class T> operator T() const
  202. {
  203. return initialized<T>().data();
  204. }
  205. };
  206. initialized_value_t const initialized_value = {} ;
  207. } // namespace boost
  208. #ifdef BOOST_MSVC
  209. #pragma warning(pop)
  210. #endif
  211. #endif