Subject: [boost] variant2 never empty guarantees (was: Re: Outcome/expected/etc/etc/etc)
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2017-06-06 09:15:53
>> 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 repeat my suggestion that for variant2:
>> 1. If at least all types minus one have nothrow move construction, you
>> get the strongest possible never empty never change guarantee.
>> 2. If the user is dumb enough to supply more than one type with a
>> throwing move constructor, they get the current C++ 17 variant valueless
>> by exception semantics i.e. go valueless if changing state threw an
>> exception and the previous state threw an exception on attempt to restore.
>> 3. We thus never double storage.
>> 4. And we never, EVER change state silently to something the user did
>> not explicitly ask for.
> I would recommend not mixing the design discussion of `variant2` with the
> design considerations of `outcome`. `outcome` has its own design
> constraints: it is natural to have only one type with a potentially
> throwing move constructor. In contrast, `variant2<Ts...>` cannot make any
> assumptions or guesses about `Ts...`, so it may need different
> implementation of the assignment.
I am not mixing the design discussion. I am talking about variant2 only.
I am proposing the above mix of strong never-empty never-change
guarantees when the user supplies a reasonable set of types. So:
1. If all but one of the types has a nothrow move constructor, you get
the strong never-empty never-change guarantee.
2. If more than one of the types has a throwing move constructor,
assignment still moves old state onto the stack before attempting to set
new state. If, *and only if*, **both** the move of the new state throws
and the attempt to restore the old state ALSO throws, then and only then
do we enter valueless-by-exception state.
My view here is that C++ 17 std::variant already has
valueless_by_exception(). My proposal is that it becomes a very rare
situation indeed to ever occur, and guaranteed not to occur if the types
supplied meet the conditions requested.
End user code can test if the never empty guarantee is in place using
'if constexpr(!variant.valueless_by_exception()) ...' because bool
valueless_by_exception() would become constexpr false in the
implementation with the strong never empty guarantee.
-- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/