diff --git a/include/boost/utility/value_init.hpp b/include/boost/utility/value_init.hpp index c4cd3e1..f5f04bf 100644 --- a/include/boost/utility/value_init.hpp +++ b/include/boost/utility/value_init.hpp @@ -7,103 +7,106 @@ // 21 Ago 2002 (Created) Fernando Cacciola // 07 Set 2007 (Worked around MSVC++ bug) Fernando Cacciola, Niels Dekker // 16 Nov 2007 (Refactoring: removed private base classes) Fernando Cacciola, Niels Dekker +// 09 Dec 2007 (Worked around various compiler bugs) Fernando Cacciola, Niels Dekker // #ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP #define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP -#include -#include -#include - -// Microsoft Visual C++ does not correctly support value initialization, as reported by -// Pavel Kuznetsov (MetaCommunications Engineering), 7/28/2005, Feedback ID 100744, -// Feedback Title: Value-initialization in new-expression +// Note: The implementation of boost::value_initialized had to deal with the +// fact that various compilers haven't fully implemented value-initialization: +// Microsoft Feedback ID 100744 - Value-initialization in new-expression +// Reported by Pavel Kuznetsov (MetaCommunications Engineering), 2005-07-28 // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744 -// The report was closed at 11/14/2006, and its status was set to "Closed (Won't Fix)". -// Luckily, even in the presence of this compiler bug, boost::value_initialized will still -// do its job correctly, when using the following workaround: -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500)) -# define BOOST_UTILITY_VALUE_INIT_WORKAROUND -#endif - -#ifdef BOOST_UTILITY_VALUE_INIT_WORKAROUND +// GCC Bug 30111 - Value-initialization of POD base class doesn't initialize members +// Reported by Jonathan Wakely, 2006-12-07 +// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30111 +// GCC Bug 33916 - Default constructor fails to initialize array members +// Reported by Michael Elizabeth Chastain, 2007-10-26 +// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33916 +// Borland Report 51854 - Value-initialization: POD struct should be zero-initialized +// Reported by Niels Dekker (LKEB, Leiden University Medical Center), 2007-11-09 +// http://qc.codegear.com/wc/qcmain.aspx?d=51854 +// The constructor of boost::value_initialized works around these issues, by +// clearing the bytes of T, before constructing the T object it contains. #include +#include +#include +#include #include #include #include -#ifdef BOOST_MSVC -#pragma warning(push) -#if _MSC_VER >= 1310 -// When using MSVC 7.1 or higher, placement new, "new (&x) T()", may trigger warning C4345: -// "behavior change: an object of POD type constructed with an initializer of the form () -// will be default-initialized". There is no need to worry about this, though. -#pragma warning(disable: 4345) -#endif -#endif - namespace boost { template class value_initialized { private : - mutable typename ::boost::aligned_storage::value>::type x; + struct wrapper + { +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) + typename +#endif + remove_const::type data; + }; + + mutable +#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x592)) + typename +#endif + ::boost::aligned_storage::value>::type x; public : value_initialized() { std::memset(&x, 0, sizeof(x)); - new (&x) T(); +#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". There is no need to worry about this, though. +#pragma warning(disable: 4345) +#endif +#endif + new (&x) wrapper(); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + } + + value_initialized(value_initialized const & arg) + { + void const * const ptr = &(arg.x); + new (&x) wrapper( *static_cast(ptr) ); + } + + value_initialized & operator=(value_initialized const & arg) + { + T & this_data = this->data(); + T const & arg_data = arg.data(); + this_data = arg_data; + return *this; } ~value_initialized() { - void * ptr = &x; - static_cast(ptr)->T::~T(); + void * const ptr = &x; + static_cast(ptr)->wrapper::~wrapper(); } T& data() const { - void * ptr = &x; - return *static_cast(ptr); + void * const ptr = &x; + return static_cast(ptr)->data; } operator T&() const { return this->data(); } } ; -#ifdef BOOST_MSVC -// Restores the state of warning C4345. -#pragma warning(pop) -#endif - -#else - -namespace boost { - -template -class value_initialized -{ - public : - - value_initialized() : x() {} - - T& data() const { return x; } - - operator T&() const { return this->data(); } - - mutable -#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) - typename -#endif - ::boost::remove_const::type x ; - -} ; -#endif - template