Hello Andrzej and all,
On Wed, Nov 29, 2017 at 11:48 PM, Andrzej Krzemienski via Boost
Let me give you some context. I would like to create a RAII-like class representing a session with an open file. When I disable all moves and copies and the default constructor (so that it is a guard-like object) I can provide a very useful guarantee: When you have an object of type `File` within its lifetime, it means the file is open and you can write to it, or read from it.
This means calling `file.write()` and `file.read()` is *always* valid and always performs the desired IO operation. When it comes to expressing invariant, I can say:
``` bool invariant() const { this->_file_handle != -1; } ```
(assuming that -1 represents "not-a-handle")
But my type is not moveable. So I add move operations (and not necessarily the default constructor), but now I have this moved-from state, so my guarantee ("When you have an object of type `File` within its lifetime, it means the file is open and you can write to it, or read from it") is no longer there. You may have an object to which it is invalid to write. Of course, the moved-from-object is still "valid", but now "valid" only means "you can call function `is_valid()` and then decide" (and of course you can destroy, assign, but that's not the point).
Now, in turn, every function like `read()` or `write()` has a precondition: `is_valid()`. So object is always "valid" but calling 90% of its interface is invalid (unless you guarantee the precondition manually).
The invariant informally is "either in a moved-from-state or you can use write/read", and there may be no way to express it in the code. This is still an "invariant", but it is *weak*, that is, it is less useful in practice. The previous invariant (in the guard-like design) is *strong* it has practical value to the user: I do not have to check anything before calling `read()`.
The new invariant is *weak*: you have to "check" something time and again, and the design is more prone to bugs: you can call functions out of contract.
I agree. In code:
#include