设置流状态以在格式化输出运算符 (operator<<) 中传达错误
Set stream state to communicate error in formatted output operator (operator<<)
我认为最佳做法是在给定输入不可用时在输入流上设置故障位。但是我想知道为什么我找不到在 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;
}
问题:我想知道是否还应该在输出流上设置故障位(如果适用)。
请考虑以下示例:
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。)
最后我想知道我是否可以、应该或避免在 ostream 上设置 failbit 以及为什么。
您所描述的案例的标准做法是编写一些无效值的表示形式。通常不需要将其标记为错误。例如,如果出现数值 42,您可以写“? (42)”。或者可能只是“42”,如果您希望能够使用 operator >>
.
轻松地将文本返回到枚举
只是从评论中总结我的结论(感谢一些程序员的输入)...
您将两个问题混为一谈,最好分开:
a) 枚举值可能无效
b) 流式传输到 os
可能会失败
可以说 a) 并不真正属于 operator<<
重载。如果您想确保枚举有效,那么您可能还想在其他地方检查它,而不仅仅是在流式传输时。实际上你应该在之前这样做,以便能够尽快检测到错误,而不仅仅是当它到达 user/outside 世界时。另一方面,从我的头顶上我不知道如何使用范围枚举到达 default
除非你故意尝试做错事。在那种情况下,你只会得到你应得的。不要过度保护。
对于 b),您不需要在代码中做任何额外的事情。如果
os << "1";
确实失败了,那么这个调用已经为你设置了失败位。
TL;DR:您可能不需要 operator<<
中的检查。如果您认为需要检查,那么 operator<<
仍然不是放置它的正确位置。
我认为最佳做法是在给定输入不可用时在输入流上设置故障位。但是我想知道为什么我找不到在 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;
}
问题:我想知道是否还应该在输出流上设置故障位(如果适用)。
请考虑以下示例:
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。)
最后我想知道我是否可以、应该或避免在 ostream 上设置 failbit 以及为什么。
您所描述的案例的标准做法是编写一些无效值的表示形式。通常不需要将其标记为错误。例如,如果出现数值 42,您可以写“? (42)”。或者可能只是“42”,如果您希望能够使用 operator >>
.
只是从评论中总结我的结论(感谢一些程序员的输入)...
您将两个问题混为一谈,最好分开:
a) 枚举值可能无效
b) 流式传输到 os
可能会失败
可以说 a) 并不真正属于 operator<<
重载。如果您想确保枚举有效,那么您可能还想在其他地方检查它,而不仅仅是在流式传输时。实际上你应该在之前这样做,以便能够尽快检测到错误,而不仅仅是当它到达 user/outside 世界时。另一方面,从我的头顶上我不知道如何使用范围枚举到达 default
除非你故意尝试做错事。在那种情况下,你只会得到你应得的。不要过度保护。
对于 b),您不需要在代码中做任何额外的事情。如果
os << "1";
确实失败了,那么这个调用已经为你设置了失败位。
TL;DR:您可能不需要 operator<<
中的检查。如果您认为需要检查,那么 operator<<
仍然不是放置它的正确位置。