I believe it is a best practice to set the failbit on an input stream when a given input is not usable. However I wonder why I don't find evidence to do the same on ostreams.
For example cppreference has the following examples for overloading operators << and >>.
std::ostream& operator<<(std::ostream& os, const T& obj)
{
// write obj to stream
return os;
}
std::istream& operator>>(std::istream& is, T& obj)
{
// read obj from stream
if( /* T could not be constructed */ )
is.setstate(std::ios::failbit);
return is;
}
Question: I wonder if one should also set the failbit on the output stream (if applicable).
Please consider the following example:
enum class enumeration
{
ONE,
TWO
};
std::ostream& operator<<(std::ostream& os, const enumeration& e)
{
switch (e)
{
case enumeration::ONE:
os << "1";
break;
case enumeration::TWO:
os << "2";
break;
default:
os.setstate(std::ios::failbit); // <-- line in question
break;
}
return os;
}
Is the line in question reasonable or not? (I put a working example here cpp.sh.)
In the end I wonder whether I can, should or avoid setting the failbit on ostreams and why.
Just summarizing my conclusions from comments (thanks to Some programmer dude for the input)...
You are mixing two concerns that you better keep seperated:
a) the value of the enum could be invalid
b) streaming to os
can fail
One can argue that a) does not really belong into the operator<<
overload. If you want to make sure that the enum is valid, then you want to check this maybe also in other places not only when streaming it. Actually you should do it before, to be able to detect an error as soon as possible, not only when it reaches the user/outside world. On the other hand, from the top of my head I dont know how you could reach the default
with a scoped enum unless you deliberately try to do something wrong. In that case you just get what you deserve. Don't be overprotective.
For b) you do not need to do anything extra in your code. If
os << "1";
does fail, then this call will already set the failbit for you.
TL;DR: You probably do not need the check in the operator<<
. If you think you need the check then operator<<
is still not the right place to put it.