应该在我的自定义 >> 运算符中调用 istream::clear() 吗?

Should call istream::clear() in my custom >> operator?

我正在编写一个自定义 >> 运算符,它逐个字符地读取整个流并使用每个字符更新一个对象,如下所示:

class MyClass 
{
    public:
        bool Process(char c);
}

std::istream& operator>>(std::istream& input, MyClass& value)
{
    if (input)
    {
        char c;
        bool parsing_success = true;

        while (parsing_success && input >> c)
        {
            parsing_success = value.Process(c)
        }

        if (!parsing_success)
            input.setstate(std::ios_base::failbit);            
    }

    return input;
}

这个想法是一个字符一个字符地读取流,直到到达流的末尾或直到遇到 MyClass 不喜欢的字符。当后者发生时,运算符将引发错误。

我打算像这样使用它:

MyClass value;

if (std::cin >> value)
{
    //do something with value
}
else
{
    //handle error
}

我遇到的问题是,在读取整个流后,istream::fail() return 为真,因为已到达流的末尾,这同时设置了 eoffail(如 等其他问题所示)。

结果 std::cin >> value return即使流已成功处理也是错误的。

现在,运算符的调用者可能会检查是否设置了 eof 位,但我觉得这与 >> 运算符的其他标准使用模式不符合习惯 - 例如int x; if (cin >> x) { //do something }.

所以我的问题是 - 我应该在成功处理流后调用 istream::clear 吗?。像这样:

if (!parsing_success)
    input.setstate(std::ios_base::failbit); 
else
    input.clear();

这将清除 failbit 并确保 std::cin >> value 仅在存在合法流错误或遇到无效字符时才 return false。但是,我只是不确定这是惯用的 C++ 还是会导致其他问题。

谢谢!

Should I be calling istream::clear after successfully processing the stream?

这很好,因为您的流成功读取了整个输入,而这正是您的用户定义的 operator>>() 应该做的,因此它应该报告成功。我会更改它以清除除 ios_base::eofbit 之外的掩码,因为这是用户可以使用的额外信息,并且不会影响 if 语句:

if (!parsing_success)
  input.setstate(std::ios_base::failbit); 
else
  input.clear(std::ios_base::eofbit);