设置流状态以在格式化输出运算符(运算符<

问题描述 投票:0回答:2

我认为最佳做法是在给定输入不可用时在输入流上设置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以及为什么。

c++ operators outputstream
2个回答
0
投票

只是总结我的评论结论(感谢一些程序员老兄的意见)......

你混合了两个你最好分开的问题:

a)枚举的值可能无效

b)流式传输到os可能会失败

人们可以争辩说a)并不真正属于operator<<超载。如果你想确保枚举有效,那么你想要在其他地方检查这个,不仅仅是在流式传输时。实际上你应该之前做到这一点,以便能够尽快发现错误,而不仅仅是当它到达用户/外部世界时。另一方面,从我的头顶我不知道你怎么能用一个范围枚举达到default除非你故意试图做错事。在这种情况下,你得到你应得的。不要过度保护。

对于b),您不需要在代码中执行任何额外操作。如果

 os << "1";

确实失败了,那么这个调用已经为你设置了failbit。

TL; DR:您可能不需要在operator<<中进行检查。如果您认为需要检查,那么operator<<仍然不适合放置它。


0
投票

您所描述的案例的标准做法是写一些无效值的表示。通常不需要将其标记为错误。例如,如果出现数值42,则可以写“?(42)”。或者只是“42”,如果您希望能够使用operator >>轻松地将文本往返回枚举。

© www.soinside.com 2019 - 2024. All rights reserved.