为什么运营商&gt;&gt;如果它达到EOF,复杂的<double>没有设置eofbit?

时间:2016-06-16 12:45:21

标签: c++ std eof complex-numbers istream

我正在尝试从文件(或任何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;

输出

 val = (4,0)
 val = (1.2,0)
 flags: eof=0 fail=1 bad=0

如果我将std::complex<double>替换为double,它会按预期工作,产生

 val = 4
 val = 1.2
 flags: eof=1 fail=1 bad=0

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

run on coliru with g++

run on coliru with clang++ and libc++

编辑我从2013年发现了一个bug report,但问题似乎仍然存在,而且这个库很常见。有没有办法让我可以让任何人都可以使用自己的解析器?

1 个答案:

答案 0 :(得分:1)

源于标准措辞:

  

<强> [complex.ops]
  12 效果:提取表单的复数 x u ,    (u)(u,v),其中 u 是真实的部分, v 是虚构的part(27.7.2.2)。
  13 需要:输入值应可转换为T。如果遇到输入错误,请拨打is.setstate(ios_base::failbit)(可能会抛出ios::failure(27.5.5.4)。)   14 退货is
  15 备注:此提取是作为一系列更简单的提取执行的。因此,对于每个更简单的提取,指定空白的跳过是相同的。

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