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