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
(), 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/