Boost logo

Boost :

From: Douglas Gregor (gregod_at_[hidden])
Date: 2002-08-09 13:27:25

On Friday 09 August 2002 12:52 pm, David Abrahams wrote:
> > We decided long ago that #1 is bad, because it makes variants harder to
> use.
> > But if we choose #2, then the current assign/swap semantics don't meet
> the
> > basic guarantee!
> I don't understand why that must be the case. Are we still working with
> assign_as<T>, swap_as<T> et al?
> If so, it seems to me that these can just dispatch to the operation defined
> for T, and assuming T's assignment meets the basic guarantee, all is well.

Because we have to handle the case where we are assigning a T to a U. For

void foo(T& t, U& u)
  variant<T, U> v(t);
  v = u;

Prior to the assignment "v = u", we have memory inside 'v' that stores a value
of type 'T'. After the assignment "v = u", that same memory inside 'v' will
store a value of type 'U'. Because the U needs to occupy the same space as
the T does now, the T must be destructed before the U is constructed.
However, U's construction can throw so we need to save the value of T. That's
fine, but how do we _restore_ the saved value of T? For instance, say we do

char the_memory[max_sizeof(T, U)];

variant& operator=(const U& u)
  T* asT = reinterpret_cast<T*>(&the_memory[0]);
  T savedT(*asT); // save a copy of the T value. it's okay if this throws
  asT->~T(); // destroy the T, won't throw

  try {
    new (&the_memory[0]) U(u); // might throw
  catch(...) {
    // restore the T value

What goes in that catch block? We can't copy-construct savedT into the_memory,
because that might throw and we'd be left with the_memory in an inconsistent
state. We can't use T's assignment operator because there's no T there.

> I don't expect to be able to repair exception-broken types (i.e. those
> whose operations don't even meet the basic guarantee).

That's fine. Unfortunately, the problem above occurs even with types whose
assignment and copy constructor meet the strong guarantee.


Boost list run by bdawes at, gregod at, cpdaniel at, john at