I wonder if the following syntax can be “admitted” or if good practices consider this as coming from hell. The goal would be to add a level of protection to force the developer to be well-conscious of what he is doing. Here is the syntax :
class MyClass
{
public:
template<bool RemoveProtection = false>
inline std::ofstream& writeStream()
{
static_assert(RemoveProtection, "You're doing it wrong");
return _writeStream;
}
inline const std::ofstream& writeStream() const
{
return _writeStream;
}
protected:
std::ofstream _writeStream;
};
The use would be :
x.writeStream().good(); // <- OK
x.writeStream().put('c'); // <- NOT OK
x.writeStream<true>().put('c'); // <- OK
I find this as a convenient way to tell to the developer : “Beware, you are using a low-level function and you have to be careful with what you are doing”. Is it a “acceptable” way of providing a direct access to class members with a kind of “protection” ? Is there other way of coding a such thing ?
Have a look at meagar’s comment:
A class you provide to others should never be able to get into an unpredicted state when another user uses it. An unpredicted state is in this case a state which you never considered when you were writing the class. As such you should either never allow access to low-level methods of your class or document possible flaws.
Lets say you’re writing a logger:
Ignore that there isn’t a copy constructor and that the assignment operand is missing. Also ignore that it’s a crude logger, it doesn’t even provide a timestamp. However, as you can see, the state of the logger depends completely on the logger’s methods, e.g. if the file has been successfully opened it won’t be closed until the logger gets destroyed.
Now say that we use your approach:
And now someone uses the following code
Bang. Your logger is broken. Of course it’s the users fault, since they used
<true>, didn’t they? But more often than not a user is going to copy example code, especially if he uses a library for the first time. The user sees your exampleand ignores the documentation completely at first. Then he’s going to use the first and the last version. Later he discovers that the last version works every time! What a miraculous thing
<true>is. And then he starts to blame you for evil things that happen, so you have protect yourself from blatant flames with a documentation which includes a warning:So, what did we get? We still had to put that warning somewhere. It would have been much simpler if we made
streampublic:or sticked to
Woops. So either don’t allow access to your low-level methods (build a wrapper to specific
std::ofstreammethods if they should be allowed to use them) or document the possible flaws which can happen if you alter the object’s internals to much, but don’t go the middle-way and make it look okay with astatic_assert.