diff --git a/include/boost/utility/value_init.hpp b/include/boost/utility/value_init.hpp index 5aefac9..5de9585 100644 --- a/include/boost/utility/value_init.hpp +++ b/include/boost/utility/value_init.hpp @@ -9,6 +9,8 @@ // 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 +// 30 May 2010 (Made memset call conditional, fixing #3869) Niels Dekker // #ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP #define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP @@ -20,6 +22,7 @@ // contains. More details on these issues are at libs/utility/value_init.htm #include +#include // For BOOST_NO_COMPLETE_VALUE_INITIALIZATION. #include #include #include @@ -28,10 +31,39 @@ #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) +// It is safe to ignore the following MSVC warning, which may pop up when T is +// a const type: "warning C4512: assignment operator could not be generated". +#pragma warning(disable: 4512) +#endif +#endif + +#ifdef BOOST_NO_COMPLETE_VALUE_INITIALIZATION + // Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED + // suggests that a workaround should be applied, because of compiler issues + // regarding value-initialization. + #define BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED +#endif + +// Implementation detail: The macro BOOST_DETAIL_VALUE_INIT_WORKAROUND +// switches the value-initialization workaround either on or off. +#ifndef BOOST_DETAIL_VALUE_INIT_WORKAROUND + #ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED + #define BOOST_DETAIL_VALUE_INIT_WORKAROUND 1 + #else + #define BOOST_DETAIL_VALUE_INIT_WORKAROUND 0 + #endif +#endif + namespace boost { template -class value_initialized +class initialized { private : struct wrapper @@ -40,6 +72,18 @@ class value_initialized typename #endif remove_const::type data; + + wrapper() + : + data() + { + } + + wrapper(T const & arg) + : + data(arg) + { + } }; mutable @@ -55,30 +99,25 @@ class value_initialized public : - value_initialized() + initialized() { +#if BOOST_DETAIL_VALUE_INIT_WORKAROUND 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 ); @@ -86,7 +125,7 @@ class value_initialized return *this; } - ~value_initialized() + ~initialized() { wrapper_address()->wrapper::~wrapper(); } @@ -101,17 +140,81 @@ class value_initialized 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 : + + value_initialized() + : + m_data() + { } + + 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 @@ -119,6 +222,7 @@ T const& get ( value_initialized const& x ) { return x.data() ; } + template T& get ( value_initialized& x ) { @@ -138,7 +242,7 @@ class initialized_value_t template operator T() const { - return get( value_initialized() ); + return initialized().data(); } }; @@ -147,5 +251,8 @@ initialized_value_t const initialized_value = {} ; } // namespace boost +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif #endif