为什么 std::ios_base::ignore() 设置 EOF 位?

Why does std::ios_base::ignore() set the EOF bit?

当我从一个流中读取所有数据,但没有尝试读取它的末尾时,没有设置该流的 EOF。这就是 C++ 流的工作方式,对吧?这就是它起作用的原因:

#include <sstream>
#include <cassert>

char buf[255];

int main()
{
    std::stringstream ss("abcdef");
    ss.read(buf, 6);

    assert(!ss.eof());
    assert(ss.tellg() == 6);
}

但是,如果我 ignore() 不是 read()ing 数据,则设置 EOF:

#include <sstream>
#include <cassert>

int main()
{
    std::stringstream ss("abcdef");
    ss.ignore(6);

    assert(!ss.eof());        // <-- FAILS
    assert(ss.tellg() == 6);  // <-- FAILS
}

这是在 GCC 4.8 和 GCC trunk (Coliru) 上。

它还有一个不幸的副作用,那就是 tellg() return -1(因为那是 tellg() 所做的),这让我很恼火做。

这个标准是强制性的吗?如果有,是哪一段以及为什么?为什么 ignore() 会尝试阅读比我告诉它的更多的内容?

我在 cppreference's ignore() page 上找不到这种行为的任何原因。我可能可以 .seekg(6, std::ios::cur) 代替,对吧?但我还是想知道是怎么回事。

我认为这是一个 libstdc++ 错误 (42875, h/t NathanOliver)。 [istream.unformatted]中ignore()的要求是:

Characters are extracted until any of the following occurs:
n != numeric_limits<streamsize>::max() (18.3.2) and n characters have been extracted so far
— end-of-file occurs on the input sequence (in which case the function calls setstate(eofbit), which may throw ios_base::failure (27.5.5.4));
traits::eq_int_type(traits::to_int_type(c), delim) for the next available input character c (in which case c is extracted).
Remarks: The last condition will never occur if traits::eq_int_type(delim, traits::eof()).

所以我们有两个条件(最后一个被忽略)——我们要么读取 n 个字符,要么在某个时候到达文件末尾,在这种情况下我们设置 eofbit。但是,在这种情况下,我们能够从流中读取 n 个字符(实际上您的流中有 6 个字符),因此我们不会在输入序列上到达文件末尾。

在 libc++ 中,eof() 未设置,tellg() 设置 return 6.