为什么复杂的<double>上的operator >>如果达到EOF则没有设置eofbit?

den*_*nis 9 c++ std istream complex-numbers eof

我试图std::complex<double>从文件(或任何std::istream)中尽可能多地阅读.如果操作失败,我检查ios :: eof().如果尚未设置,我认为解析数据时出错,我可以向用户报告输入文件有错误.这种方案适用于双重,但不知何故它在复数上失败.为什么?

以下是一些重现问题的代码:

std::istringstream istr("4 1.2");
std::complex<double> val;

while( istr >> val )
        std::cout << " val = " << val << std::endl;

std::cout << "flags: eof=" << istr.eof() << " fail=" << istr.fail() << " bad=" << istr.bad() << std::endl;
Run Code Online (Sandbox Code Playgroud)

输出是

 val = (4,0)
 val = (1.2,0)
 flags: eof=0 fail=1 bad=0
Run Code Online (Sandbox Code Playgroud)

如果我更换std::complex<double>double,它按预期工作,产生

 val = 4
 val = 1.2
 flags: eof=1 fail=1 bad=0
Run Code Online (Sandbox Code Playgroud)

libstdc ++会出现此问题,但它似乎与libc ++一起使用:

使用g ++在coliru上运行

使用clang ++和libc ++在coliru上运行

编辑我发现了2013年的错误报告,但问题似乎仍然存在,而且库很常见.我有没有办法让它适合任何人,而无需编写我自己的解析器?

Rev*_*lot 1

它源于标准措辞:

[complex.ops]
12效果:提取以下形式的复数x : u(u)(u,v),其中u是实部,v是虚部 (27.7.2.2)。
13要求:输入值应可转换为T。如果遇到错误的输入,则调用is.setstate(ios_base::failbit)(可能会抛出ios::failure(27.5.5.4))。
14返回is.
15备注:此提取是作为一系列更简单的提取来执行的。因此,对于每个更简单的提取,空白的跳过被指定为相同。

特别是它没有指定eofbit在任何情况下都应该设置。即使注释也没有指定执行什么操作以及它们的语义是什么。有一个关于它的缺陷报告,它建议通过指定操作语义来解决问题,如果幸运的话,它将进入 C++17。