Why does operator>> on complex<double> not set eofbit if it reaches EOF?
Asked Answered
J

1

9

I'm trying to read as many std::complex<double> as possible from a file (or any std::istream). If the operation fails, I check for ios::eof(). If it hasn't been set, I assume that there was an error in parsing the data, and I can report to the user that the input file has errors. This scheme works for double, but somehow it fails on complex numbers. Why?

Here is some code to reproduce the problem:

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;

The output is

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

If I replace std::complex<double> with double, it works as expected, yielding

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

This problem occurs with libstdc++, but it seems to work with libc++:

run on coliru with g++

run on coliru with clang++ and libc++

EDIT I found a bug report from 2013 but the problem still seems to be there, and the library is quite common. Is there a way for me to make it work for anybody without having to write my own parser?

Jacquetta answered 16/6, 2016 at 12:45 Comment(3)
Why would you need to write your own parser? Why not simply read two doubles from the stream, and use those to construct a complex<double>?Pinxit
Because I need the flexibility of serialization that complex<double> offers. It recognizes double, (double) and (double,double)Jacquetta
The whole complex extractor business is extremely underspecified, but the implementation here is clearly broken too.Prober
T
1

It stems from standard wording:

[complex.ops]
12 Effects: Extracts a complex number x of the form: u, (u), or (u,v), where u is the real part and v is the imaginary part (27.7.2.2).
13 Requires: The input values shall be convertible to T. If bad input is encountered, calls is.setstate(ios_base::failbit) (which may throw ios::failure (27.5.5.4)).
14 Returns: is.
15 Remarks: This extraction is performed as a series of simpler extractions. Therefore, the skipping of whitespace is specified to be the same for each of the simpler extractions.

In particular it does not specify that it should set eofbit in any case. Even remark does not specify what operations are performed and what their semantic is. There is a Defect Report about it, which suggest resolution by specifying semantic of operation and, if we are lucky, it will make its way to C++17.

Terra answered 16/6, 2016 at 13:24 Comment(2)
"... and resolution should be included in C++17" You are more optimistic than I am. Let's see what LWG does with it.Prober
@Prober Oh, you are right. I do not know, how I misread "Proposed resolution" as "Resolved"Terra

© 2022 - 2024 — McMap. All rights reserved.