Boost logo

Boost :

From: Itay Maman (itay_maman_at_[hidden])
Date: 2002-08-09 20:04:36


"Fernando Cacciola" <fcacciola_at_[hidden]> wrote in message
news:00c201c23fe3$08f81f80$0f00a8c0_at_fernandoc...
>
[snip]

>
> I agree that empty variants should be avoided as much as possible.
>
> But as I said in a previous message, I don't think that variant should
> struggle so badly to keep itself consistent when it is feed with types
which
> can't.
> If such consistency could be achieved more or less nicely; I'd go for it,
> but the more we think of it the more we realize how difficult it is, not
in
> terms of intelectual excercise, but in terms of space and/or time
overhead.
>
Visiting an empty variant is a singular case. Each of the possible
approaches for handling this situation (exception, assert, a call-back
function, an "undefined state" warning in the documentation) is highly
unattractive. That is why I am willing to pay a high price (in terms of code
complexity), to eliminate the empty state altogether.

> To reiterate my position:
>
> If the user-defined copy-ctor throws, AND variant does NOTHING, not even
> resetting 'v' to empty before the assignment, the variant lvalue will be
> left undefined. Not empty, just plain inconsistent.
> This sounds terrifying, but it isn't, because a user defined type whose
> copy-constructor throws will most likely define an assignment operator
which
> also throws, so the situation won't be any worse than working with this
> broken-type (as David called it) directly.
>
You are assuming that if a type T offers an assignment operation which
upholds the basic or strong guarantee, it is possible to implement a
variant, such that it offers similar exception-safety guarantee when
assigned with a value of type T.

Well, I think it is not possible to implement such a variant. The reason:
When you assign a value of type T to a variant, you actually want an object
of type T to overwrite a object of a different class/type. This means that
you *cannot* use T's copy constructor/swap facility to achieve the desired
result, since these operations assume that both objects (source and
destination) are of type T.

Let me state the problem: Given two types T1, T2 and two respective
instances: t1, t2, we'd like to (a) create a copy of t2 in the same memory
address as t1 and (b) appropriately destroy t1. The order of (a) and (b)
can be reversed. Strong exception safety is required. (Let's assume that
both buffers are of a sufficient size, with the proper alignment).

We already have solutions for these simplified situations:
1) The new instance of t2 does not have to 'overwrite' t1
2) Only basic exception safety guarantee is required.

> IMO, since variant<> is essentially a compound type, exception-free
> assignment should be guaranteed by the types it contains, not by itself.
We
> shouldn't except it to do more than whatever the types themselves do.
>
> Besides, it will always be possible for a user to wrap offending types.
>
> Also, the current implementation uses the copy-ctor in place of the
> assignment operator. This shouldn't be a problem, though, but unless
> *really* necessary, I wouldn't bypass T's operator=.
>
As explained above, T's operator= is practically useless with respect to
variant::operator=.

--
Itay Maman
    itay_maman@_yahoo_.com
    maman_at_il._ibm_.com
This message expresses my personal opinion.

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