Boost logo

Boost :

Subject: Re: [boost] Strong guarantee variant (Was: Outcome/expected/etc/etc/etc)
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2017-06-06 10:58:59


On 06/06/2017 11:37, Peter Dimov via Boost wrote:
> Niall Douglas wrote:
>
>> I hate with a passion any possibility of a variant changing its state
>> without me explicitly telling it to do so. The only tolerable state a
>> variant should ever choose on its own is empty/valueless.
>
> I wonder whether the people who insist on the strong guarantee on
> assignment realize that when the variant holds a vector, and you assign
> it a vector, assignment delegates to vector<>::operator= and as a result
> you get the basic guarantee because that's what all standard types provide.

I'd expect nothing else. No state change means you always pass through
to operator=().

> It's possible to define a variant that never delegates to the assignment
> operator of the contained type. I've also argued for this possibility,
> because it makes it possible for one to put non-assignable types into
> variant (and optional, if it's changed to match), and still get an
> assignable variant.
>
> Nevertheless, this is not the case today, and I suspect that you don't
> realize that the strong guarantee requires this change.

Assign same state => operator=() of underlying type

Assign new state => move/copy constructor of underlying type.

>> 1. If at least all types minus one have nothrow move construction, you
>> get the strongest possible never empty never change guarantee.
>
> What do you do on emplace<throwing_move>(), when the variant already
> contains 'throwing_move'?

1. Move old state onto stack.

2. Emplace new state.

3. If it throws, move stacked state back.

4. If that throws, go to valueless.

> And what do you do on operator=( throwing_move ), when the variant
> already contains 'throwing_move' and throwing_move::operator= doesn't
> provide the strong guarantee?

That's on the type in question. Nothing to do with a variant
implementation. It only gets involves when state is being changed,
otherwise always pass through.

My proposed semantics are not complicated. Keep it simple. Much stronger
never-empty guarantees than std::variant, but only if the user plays
ball. If they don't play ball, we try better than std::variant does to
avoid valueless.

BTW I made an error to suggest valueless_by_exception() should go
constexpr earlier, it already always is. I'd suggest instead the member
function completely vanish if you have the strong never-empty guarantee
thanks to choosing the right types.

Niall

-- 
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/

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