|
Boost : |
From: Fernando Cacciola (fernando_cacciola_at_[hidden])
Date: 2002-11-21 10:01:02
Hi all!
In a private conversation with Eric Friedman about the implementation of
optional<> the following issue came out:
My implementation claims to achieve the strong exception guarantee: leaving
the optional unchanged in case of an exception during assignment or swap,
based on a trick which yields undefined behavior for **arbitrary types**.
However, I believe that if instead of arbitrary types, optional<T> is
restricted to types which are required to be 'address independent' (I'll
explain this shortly), the behavior is well defined.
The trick is to use placement new to construct the object at a given aligned
address and then byte-move it to another aligned address.
For example, the assignment is implemented as {sketched}
template<class T>
class optional
{
typedef typename make_aligned_storage<T>::type storage_type ;
storage_type m_storage ;
T* m_v ;
optional& operator= ( optional const& rhs )
{
if ( !!rhs.m_v )
{
storage_type tmp ;
new (tmp.address()) T ( *rhs.m_v ) ; // can throw
destroy(); // no-throw
storage.swap_bytes( tmp); // no-throw
m_v = storage.address();
}
else
{
destroy();
}
return *this ;
}
void destroy()
{
if ( !!m_v)
{
m_v->~T();
m_v = 0 ;
}
}
Now, I know the above is undefined behavior for all conceivable types; but I
wonder if it is correct that the following requirement will make it defined
for those types fulfilling it:
"Address Independence: In order to preserve ALL the object invariants, ONLY
the CONTENTS of the object storage must be preserved. If the ADDRESS of the
object's storage changes during the lifetime of the object, all its
invariants shall be preserved."
IOWs, the object might not make any assumptions about the memory address it
is located at, nor impose any requirement on such an address (besides
alignment).
The question is: if the above is fulfilled by a type T, is it defined
behavior to implement assignment as in the sketch above? Or are there other
sources of undefinition?
The point is that I believe that it is always possible to *portably* tell
whether a given type T is address independent. It is a property of the
object's functionality and not of the C++ implementation. Additionally, I
believe that almost all the types that one might wrap into optional<> are
effectively address independent.
TIA,
Fernando Cacciola
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk