Boost logo

Boost :

Subject: Re: [boost] [variant2] Need rationale for never-empty guarantee
From: Peter Dimov (lists_at_[hidden])
Date: 2019-03-01 10:56:54

Andrzej Krzemienski wrote:

> But this is not the case for variant: both default-constructed state and
> the moved-from state is not "valueless", even in std::variant. The only
> way to get to a valueless state is to trigger an exception from a move
> constructor.

This is not true, by the way (although it should have been). std::variant
also goes valueless on emplace when the construction throws. I have argued
against this behavior in, which also contains
other interesting things. :-)

(It was even less true before P0308 was partially adopted.)

> And it seems to me that when this happens, the only reasonable choice for
> the user is to either reset or destroy the variant.

I can only repeat what I said about singular states. Stack unwinding in this
case is an example of "world #2" code, which can observe a valueless
variant. This means that it must be careful to never ever call an ordinary
"world #1" function on a variant object.

There's really nothing variant-specific here; the same argument applies to
any function having the basic exception safety guarantee. When you assign to
a vector, and the assignment throws, you can only reasonably reset or
destroy the vector. But we don't make it destroy-only.

And if you do have a type that is destroy-only, it breaks basic exception
safety everywhere it's used. If you assign vector<variant> and it throws,
the vector is now destroy-only.

> Yes: it makes a lot of sense to me to make an attempt to access the value
> of a valueless variant an undefined behavior. I do not associate this
> decision with the problems of types with singular states in general,
> because there is no easy way to obtain the valueless state in variant;

It doesn't have to be easy to be a problem. In fact, easy is better, because
it happens more frequently and is therefore tested.

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