
Dave Abrahams wrote:
Destructive move is practically impossible to manage regardless of exceptions:
void f() { SomeType x;
if (some_condition) { something_that_moves(x) } else { x.foo() } // Do we call x's destructor? }
After your email that explained the practical equivalence of destructive moves with raw moves, I find this example illuminating because it shows a problem that doesn't apply to raw moves. Suppose that the example concerns raw moves instead of destructive moves. In that case there is no choice at the end of f(): x' destructor will be called regardless of the truth value of some_condition. Furthermore we can assume that the code is unproblematic because we trust the author of something_that_moves. Either: something_that_moves(x) returns with x being in an invalid state, in which case the author has violated the rule that chains of raw moves bust be closed within the same scope; Or: something_that_moves(x) properly closes its internal chain of raw moves, in which case x is in a destructible state after function exit and there is no problem. So the conceptual difference is that in destructive moves, it is the compiler's responsibility to maintain integrity, while in raw moves it is the programmer's responsibility. For programmers there are clear, strict rules* for avoiding invalid destruction of raw-moved objects. If we treat raw moves as if they are the compiler's responsibility instead, they seem intractible. -Julian * 1) Once a chain of raw moves starts, in has to finish within the same scope; 2) all operations between the start and the end of a chain of raw moves must be non-throwing. I don't think there are more rules, but there might be.