|
Boost : |
From: Hamish Mackenzie (boost_at_[hidden])
Date: 2002-02-05 14:52:26
On Tue, 2002-02-05 at 18:53, Howard Hinnant wrote:
> On Tuesday, February 5, 2002, at 01:36 PM, Hamish Mackenzie wrote:
>
> >> However if the vector uses 1 (move construct) to move the elements out
> >> of the way, and an exception is thrown while copy assigning x into
> >> place, then the vector is still in a valid state. There are no holes
> >> of
> >> uninitialized memory. Basic exception safety has been maintained.
> >
> > But even 1 will leave the source damaged will it not? So an exception
> > could still lead to double destruction of the same object.
>
> Nope. Use of #1 to move elements from the end into the unused capacity
> leaves a vector that is longer than the original with a region of
> elements in a (for example) default state in the middle. With #3 these
> middle elements are destructed. This half way state must either be
> valid, or it must be clean-up-able as one starts to copy the argument x
> in. I much prefer to keep the vector in a valid state at all times.
> This approach produces much cleaner, tighter code than doing a try/catch
> and then putting things back in order in the catch clause.
Ok I see what you mean now. So would this work for option 1?
template< class T >
void move_construct( T *destination, T &source )
{
using namespace std;
construct( destination );
move( *destination, source ); // as per previous post
}
void move_construct( int *destination, int &source )
{
*destination = source;
}
Also do we need a helper for using this on the stack?
template< class T >
move_to_here
{
unsigned char buffer_[ sizeof( T ) ];
T *get() { return reinterperet_cast< T * >( &buffer_ ); }
const T *get() const { return reinterperet_cast< T * >( &buffer_ ); }
public:
move_to_here() { construct( get() ); }
// not sure if it should have default constructor
explicit move_to_here( T &source )
{
move_construct( get(), source );
}
~move_to_here() { destroy( get ); }
operator T &() { return *get(); }
operator const T &() const { return *get(); }
};
Then you could do this
move_to_here< T > temp( x );
This might even help on compilers that do not do return value
optomization
move_to_here< T > f()
{
T x;
return move_to_here< T >( x );
}
Hamish Mackenzie
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk