
On Thu, Apr 18, 2019 at 2:41 AM Andrzej Krzemienski via Boost < boost@lists.boost.org> wrote:
x1 = std::move(x2);
This throws, and leaves the objects in an unspecified (albeit "valid") state, an exception handling is stopped prematurely, so that the objects remain in scope and the programmer makes no attempt to put their values into a known state. The only guarantee we have now is that no operation on `x1` or `x2` will cause an UB.
Not true. The only operations you can perform on those objects are either (a) ones with no preconditions or (b) those where the preconditions are checked first and found to be valid. The problem with an illegal-to-observe zombie state is that it adds an unexpected precondition to copy/move construction, and that precondition is viral. For instance, having such a precondition breaks the following: void ByRef(vector<PossiblyZombieObject>& v) { v.resize(v.capacity() + 1); // error if v contains any zombie objects } or even void ByValue(vector<PossiblyZombieObject> v) { /* ... */ } // error if v contains any zombie objects And even if callees decided that want to protect against this (and let me reiterate, that should never be a requirement), they cannot, precisely because the zombie state is illegal-to-observe. A std::variant in the valueless_by_exception state is copy/move constructible because that state is observable, and that is by design. Specifically, valueless_by_exception is not a zombie state, but it is a weakening of the invariants from "exactly 1 of n types" to "at most 1 of n types". How much that matters is ultimately what we are debating. -- Nevin ":-)" Liber <mailto:nevin@cplusplusguy.com <nevin@eviloverlord.com>> +1-847-691-1404