Ticket #3472: initialized.patch

File initialized.patch, 4.5 KB (added by niels_dekker, 13 years ago)

Adds a new template class to value_init.hpp: boost::initialized<T>

  • boost/utility/value_init.hpp

     
    99// 23 May 2008 (Fixed operator= const issue, added initialized_value) Niels Dekker, Fernando Cacciola
    1010// 21 Ago 2008 (Added swap) Niels Dekker, Fernando Cacciola
    1111// 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
    1213//
    1314#ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
    1415#define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
     
    2829#include <cstring>
    2930#include <new>
    3031
     32#ifdef BOOST_MSVC
     33#pragma warning(push)
     34#if _MSC_VER >= 1310
     35// It is safe to ignore the following warning from MSVC 7.1 or higher:
     36// "warning C4351: new behavior: elements of array will be default initialized"
     37#pragma warning(disable: 4351)
     38#endif
     39#endif
     40
    3141namespace boost {
    3242
    3343template<class T>
    34 class value_initialized
     44class initialized
    3545{
    3646  private :
    3747    struct wrapper
     
    4050      typename
    4151#endif
    4252      remove_const<T>::type data;
     53
     54      wrapper()
     55      :
     56      data()
     57      {
     58      }
     59
     60      wrapper(T const & arg)
     61      :
     62      data(arg)
     63      {
     64      }
    4365    };
    4466
    4567    mutable
     
    5577
    5678  public :
    5779
    58     value_initialized()
     80    initialized()
    5981    {
     82      // Note: the following memset call will become conditional when ticket #3869 is fixed:
     83      // https://svn.boost.org/trac/boost/ticket/3869 reported by Aleksey Gurtovoy.
    6084      std::memset(&x, 0, sizeof(x));
    61 #ifdef BOOST_MSVC
    62 #pragma warning(push)
    63 #if _MSC_VER >= 1310
    64 // When using MSVC 7.1 or higher, the following placement new expression may trigger warning C4345:
    65 // "behavior change: an object of POD type constructed with an initializer of the form ()
    66 // will be default-initialized".  It is safe to ignore this warning when using value_initialized.
    67 #pragma warning(disable: 4345)
    68 #endif
    69 #endif
     85
    7086      new (wrapper_address()) wrapper();
    71 #ifdef BOOST_MSVC
    72 #pragma warning(pop)
    73 #endif
    7487    }
    7588
    76     value_initialized(value_initialized const & arg)
     89    initialized(initialized const & arg)
    7790    {
    7891      new (wrapper_address()) wrapper( static_cast<wrapper const &>(*(arg.wrapper_address())));
    7992    }
    8093
    81     value_initialized & operator=(value_initialized const & arg)
     94    explicit initialized(T const & arg)
    8295    {
     96      new (wrapper_address()) wrapper(arg);
     97    }
     98
     99    initialized & operator=(initialized const & arg)
     100    {
    83101      // Assignment is only allowed when T is non-const.
    84102      BOOST_STATIC_ASSERT( ! is_const<T>::value );
    85103      *wrapper_address() = static_cast<wrapper const &>(*(arg.wrapper_address()));
    86104      return *this;
    87105    }
    88106
    89     ~value_initialized()
     107    ~initialized()
    90108    {
    91109      wrapper_address()->wrapper::~wrapper();
    92110    }
     
    101119      return wrapper_address()->data;
    102120    }
    103121
    104     void swap(value_initialized & arg)
     122    void swap(initialized & arg)
    105123    {
    106124      ::boost::swap( this->data(), arg.data() );
    107125    }
    108126
    109     operator T const &() const { return this->data(); }
     127    operator T const &() const
     128    {
     129      return wrapper_address()->data;
     130    }
    110131
    111     operator T&() { return this->data(); }
     132    operator T&()
     133    {
     134      return wrapper_address()->data;
     135    }
    112136
    113137} ;
    114138
     139template<class T>
     140T const& get ( initialized<T> const& x )
     141{
     142  return x.data() ;
     143}
    115144
     145template<class T>
     146T& get ( initialized<T>& x )
     147{
     148  return x.data() ;
     149}
    116150
    117151template<class T>
     152void swap ( initialized<T> & lhs, initialized<T> & rhs )
     153{
     154  lhs.swap(rhs) ;
     155}
     156
     157template<class T>
     158class value_initialized
     159{
     160  private :
     161
     162    // initialized<T> does value-initialization by default.
     163    initialized<T> m_data;
     164
     165  public :
     166
     167    T const & data() const
     168    {
     169      return m_data.data();
     170    }
     171
     172    T& data()
     173    {
     174      return m_data.data();
     175    }
     176
     177    void swap(value_initialized & arg)
     178    {
     179      m_data.swap(arg.m_data);
     180    }
     181
     182    operator T const &() const
     183    {
     184      return m_data;
     185    }
     186
     187    operator T&()
     188    {
     189      return m_data;
     190    }
     191} ;
     192
     193
     194template<class T>
    118195T const& get ( value_initialized<T> const& x )
    119196{
    120197  return x.data() ;
    121198}
     199
    122200template<class T>
    123201T& get ( value_initialized<T>& x )
    124202{
     
    138216   
    139217    template <class T> operator T() const
    140218    {
    141       return get( value_initialized<T>() );
     219      return initialized<T>().data();
    142220    }
    143221};
    144222
     
    147225
    148226} // namespace boost
    149227
     228#ifdef BOOST_MSVC
     229#pragma warning(pop)
     230#endif
    150231
    151232#endif