Le 2017-12-01 02:52, Lorenzo Caminiti via Boost a écrit :
1. Is it OK to assume I can call is_valid() on a moved-from object (so I can put it to guard invariants, preconditions, etc. and also check it in user code where needed to satisfy preconditions)? Based on the replies to this email thread so far, I think the answers is "yes".
2. How useful is a class like the one above with "crippled" invariants and is_valid() preconditions on all its useful public methods like read()? The answer seems to be: not very useful. I guess that's the price to pay for the performance gain of moving objects around...
Nobody will care to check is_valid() before every call, especially if validity is assumed in the majority of cases and invalidity a rare case. Worse, people will forget to add it to their own functions preconditions. Another thing to consider is that adding methods to the class just for the sake of expressing the contract looks like there’s something broken in the design first. As for guidelines, I strongly agree with what has been said, that non-default-constructible and move-constructible are somewhat antagonist and should raise a red flag. As for usefulness, in an ideal world you would like the compiler (or a static analysis tool) to check the contracts for you. Regarding move semantics, that’s the choice made by the rust compiler (reusing a moved-from object is a compile time error). In C++, reusing a moved-from object is perfectly valid, so you would have to resort to other mechanisms to forbid it. IMHO a tool-friendly way (which, by the way, is also user-friendly) to do that is using unique_ptr : the rule to check (nullptr dereference) is much more likely to be implemented, the users are much more likely to write x != nullptr preconditions. I’m not sure there are many cases where you, at the same time : - need the object to be not constructible (always valid) - need to transfer the ownership of the object - can’t afford the extra cost of a pointer (which is, by the way, not more expensive than checking an is_valid() function). Regards, Julien