我认为最佳做法是在给定输入不可用时在输入流上设置failbit。但是我想知道为什么我没有找到证据在ostream上做同样的事情。
例如,cppreference具有以下用于重载运算符<<和>>的示例。
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;
}
问:我想知道是否还应该在输出流上设置failbit(如果适用)。
请考虑以下示例:
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;
}
这条线是否合理? (我在这里举了一个工作示例cpp.sh。)
最后,我想知道我是否可以,应该或避免在ostreams上设置failbit以及为什么。
只是总结我的评论结论(感谢一些程序员老兄的意见)......
你混合了两个你最好分开的问题:
a)枚举的值可能无效
b)流式传输到os
可能会失败
人们可以争辩说a)并不真正属于operator<<
超载。如果你想确保枚举有效,那么你想要在其他地方检查这个,不仅仅是在流式传输时。实际上你应该之前做到这一点,以便能够尽快发现错误,而不仅仅是当它到达用户/外部世界时。另一方面,从我的头顶我不知道你怎么能用一个范围枚举达到default
除非你故意试图做错事。在这种情况下,你得到你应得的。不要过度保护。
对于b),您不需要在代码中执行任何额外操作。如果
os << "1";
确实失败了,那么这个调用已经为你设置了failbit。
TL; DR:您可能不需要在operator<<
中进行检查。如果您认为需要检查,那么operator<<
仍然不适合放置它。
您所描述的案例的标准做法是写一些无效值的表示。通常不需要将其标记为错误。例如,如果出现数值42,则可以写“?(42)”。或者只是“42”,如果您希望能够使用operator >>
轻松地将文本往返回枚举。