Boost logo

Boost :

From: Brian McNamara (lorgon_at_[hidden])
Date: 2003-10-29 09:34:34


On Wed, Oct 29, 2003 at 01:27:08AM -0800, Jaap Suter wrote:
> Well, it allows me to do exactly the thing posted in the original message;
> implement a state machine where state entries and exits are implemented
> through ctors and dtors. I can probably think of a few other cases where
> such a defined order can be exploited too.
>
> Personally, I think it makes sense conceptually too. If I use the assignment
> operator on any other class, then in a sense the existing state is destroyed
> first, and then the new state is copied in. I'm not saying that it's
> implemented like that (as no sane person would do), but the similarities are
> there. I think it makes sense to let variant behave the same.

I kind of agree with the conceptual similarity, but I don't agree that a
class "should" actually exhibit behavior like this. Again, it's all
owing to details of C++ and the "strong guarantee", but I've come to
think of assignment as

   T tmp( data );
   this->swap( tmp ); // nothrow
   // tmp.~T()

which destroys old data only after new data has been safely constructed.
Indeed, many classes might make arbitrary copies of data along the way,
too.

It's only in the (rare?) case of class which has a "nothrow inplace
constructor" that the "destroy, then create" order can be achieved while
still providing the strong guarantee. (For classes without a "singular"
state, "strong" in the previous sentence changes to "basic".)

The moral is that it's typically dangerous to put an object in a
container if you need to nail down the timing of construction/
destruction of that object. IMO the burden falls more on you (the
client) than on the container implementor (e.g. variant).

That said...

> On the other hand, I can also do what I am doing as a hack now, and use
> boost::empty as follows:
>
> variant<boost::empty, foo, bar> v;
> v = foo();
> v = boost::empty(); // make sure that foo is destroyed first;
> v = bar(); // and then construct bar.
>
> With an in_place construct, this wouldn't even be any slower than allowing
> the actual implementation to define the order.
>
> Thoughts, anyone?

... I think this is a good solution to your problem. (Indeed, it
conceptually generalizes into the way to mutate an object from state1 to
state2 without ever having these states overlap.)

-- 
-Brian McNamara (lorgon_at_[hidden])

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk