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

Lig*_*ica 9 c++ iostream std c++11

当我从流中读取所有数据但不尝试读取其结束时,未设置流的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);
}
Run Code Online (Sandbox Code Playgroud)

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

#include <sstream>
#include <cassert>

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

    assert(!ss.eof());        // <-- FAILS
    assert(ss.tellg() == 6);  // <-- FAILS
}
Run Code Online (Sandbox Code Playgroud)

这是在GCC 4.8和GCC主干(Coliru)上.

它也有做的不幸的副作用tellg()回报-1(因为那是什么tellg()呢),这是恼人我在做什么.

这是标准规定的吗?如果是这样,哪一段和为什么?为什么会ignore()尝试阅读超过我告诉它的内容?

我在cppreference的ignore()页面上找不到任何这种行为的原因.我可以.seekg(6, std::ios::cur)改为,对吧?但我仍然想知道发生了什么.

Bar*_*rry 5

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

提取字符直到发生以下任何一种情况:
- n != numeric_limits<streamsize>::max()(18.3.2)并且n到目前为止已经提取了字符
- 在输入序列上发生文件结束(在这种情况下函数调用setstate(eofbit),可能抛出ios_base::failure(27.5.5.4) );
- traits::eq_int_type(traits::to_int_type(c), delim)为下一个可用的输入字符c(在这种情况下提取c).
备注:如果,最后一个条件永远不会发生traits::eq_int_type(delim, traits::eof()).

所以我们有两个条件(最后一个被忽略) - 我们要么读取n字符,要么在某个时刻我们点击文件结尾,在这种情况下我们设置了eofbit.但是,n在这种情况下,我们能够从流中读取字符(实际上流中有6个字符),因此我们不会在输入序列上点击文件结尾.

在libc ++中,eof()未设置并tellg()返回6.