Index: boost/utility/value_init.hpp =================================================================== --- boost/utility/value_init.hpp (revision 61012) +++ boost/utility/value_init.hpp (working copy) @@ -9,6 +9,7 @@ // 23 May 2008 (Fixed operator= const issue, added initialized_value) Niels Dekker, Fernando Cacciola // 21 Ago 2008 (Added swap) Niels Dekker, Fernando Cacciola // 20 Feb 2009 (Fixed logical const-ness issues) Niels Dekker, Fernando Cacciola +// 03 Apr 2010 (Added initialized, suggested by Jeffrey Hellrung, fixing #3472) Niels Dekker // #ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP #define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP @@ -28,10 +29,19 @@ #include #include +#ifdef BOOST_MSVC +#pragma warning(push) +#if _MSC_VER >= 1310 +// It is safe to ignore the following warning from MSVC 7.1 or higher: +// "warning C4351: new behavior: elements of array will be default initialized" +#pragma warning(disable: 4351) +#endif +#endif + namespace boost { template -class value_initialized +class initialized { private : struct wrapper @@ -40,6 +50,18 @@ typename #endif remove_const::type data; + + wrapper() + : + data() + { + } + + wrapper(T const & arg) + : + data(arg) + { + } }; mutable @@ -55,38 +77,34 @@ public : - value_initialized() + initialized() { + // Note: the following memset call will become conditional when ticket #3869 is fixed: + // https://svn.boost.org/trac/boost/ticket/3869 reported by Aleksey Gurtovoy. std::memset(&x, 0, sizeof(x)); -#ifdef BOOST_MSVC -#pragma warning(push) -#if _MSC_VER >= 1310 -// When using MSVC 7.1 or higher, the following placement new expression may trigger warning C4345: -// "behavior change: an object of POD type constructed with an initializer of the form () -// will be default-initialized". It is safe to ignore this warning when using value_initialized. -#pragma warning(disable: 4345) -#endif -#endif + new (wrapper_address()) wrapper(); -#ifdef BOOST_MSVC -#pragma warning(pop) -#endif } - value_initialized(value_initialized const & arg) + initialized(initialized const & arg) { new (wrapper_address()) wrapper( static_cast(*(arg.wrapper_address()))); } - value_initialized & operator=(value_initialized const & arg) + explicit initialized(T const & arg) { + new (wrapper_address()) wrapper(arg); + } + + initialized & operator=(initialized const & arg) + { // Assignment is only allowed when T is non-const. BOOST_STATIC_ASSERT( ! is_const::value ); *wrapper_address() = static_cast(*(arg.wrapper_address())); return *this; } - ~value_initialized() + ~initialized() { wrapper_address()->wrapper::~wrapper(); } @@ -101,24 +119,84 @@ return wrapper_address()->data; } - void swap(value_initialized & arg) + void swap(initialized & arg) { ::boost::swap( this->data(), arg.data() ); } - operator T const &() const { return this->data(); } + operator T const &() const + { + return wrapper_address()->data; + } - operator T&() { return this->data(); } + operator T&() + { + return wrapper_address()->data; + } } ; +template +T const& get ( initialized const& x ) +{ + return x.data() ; +} +template +T& get ( initialized& x ) +{ + return x.data() ; +} template +void swap ( initialized & lhs, initialized & rhs ) +{ + lhs.swap(rhs) ; +} + +template +class value_initialized +{ + private : + + // initialized does value-initialization by default. + initialized m_data; + + public : + + T const & data() const + { + return m_data.data(); + } + + T& data() + { + return m_data.data(); + } + + void swap(value_initialized & arg) + { + m_data.swap(arg.m_data); + } + + operator T const &() const + { + return m_data; + } + + operator T&() + { + return m_data; + } +} ; + + +template T const& get ( value_initialized const& x ) { return x.data() ; } + template T& get ( value_initialized& x ) { @@ -138,7 +216,7 @@ template operator T() const { - return get( value_initialized() ); + return initialized().data(); } }; @@ -147,5 +225,8 @@ } // namespace boost +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif #endif