[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lmi] [PATCH] Fix trailing whitespace detection in stream_cast()
From: |
Greg Chicares |
Subject: |
Re: [lmi] [PATCH] Fix trailing whitespace detection in stream_cast() |
Date: |
Wed, 29 Jan 2020 12:53:50 +0000 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.3.0 |
On 2020-01-29 12:06, Vadim Zeitlin wrote:
> On Tue, 28 Jan 2020 18:46:15 +0000 Greg Chicares <address@hidden> wrote:
[...]
> GC> std::istringstream interpreter("123");
> GC> int n = -1;
> GC> interpreter >> n;
> GC> what is this code
> GC> !(interpreter >> std::ws).eof())
> GC> supposed to do?
> GC> - it invokes the std::ws extractor; in this case, eofbit was set
> GC> by the ctor, so the effect is to set failbit; then
> GC> - eof() is called; it ignores failbit, inspects eofbit, and
> GC> returns true. Right?
>
> Yes, except for "set by the ctor" part which I don't understand.
I had misstated a technical detail:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88034
| 6 std::istringstream is("123");
| 7
| 8 std::cout << "eof/fail/bad bit values: "
| 9 << is.eofbit << ", "
| 10 << is.failbit << ", "
| 11 << is.badbit << "\n";
| 12
| 13 std::cout << "Initial state: " << is.rdstate() << "\n";
Here, all compilers agree: initial state is zero, and all of
{eofbit, failbit, badbit} are unset.
| 15 int n = -1;
| 16 is >> n;
| 17 std::cout << "After reading \"" << n << "\": " << is.rdstate() <<
"\n";
Here, all compilers agree: eofbit is set; {failbit, badbit} are unset.
| 18
| 19 is >> std::ws;
| 20 std::cout << "After ws: " << is.rdstate() << "\n";
Here, the ms compiler correctly has set both eofbit and failbit.
Reason: before extracting anything, std::ws constructs a sentry:
| [istream.unformatted]/1, starting with:
|
| Each unformatted input function begins execution by constructing an object of
| class sentry with the default argument noskipws (second) argument true
and the sentry's ctor (not the std::istream's ctor) sets eofbit.
Then, because eofbit had already been set, std::ws sets failbit.
| But the
| important thing is that the state of the stream after extracting ws() is
| completely ignored here and the exclamation sign tests the state of the
| stream after calling eof() on it.
I believe the exclamation sign in this context:
> GC> what is this code
> GC> !(interpreter >> std::ws).eof())
> GC> supposed to do?
actually tests the return value of eof(): true if eofbit is set,
false otherwise. It doesn't test the state of the stream. It's
parsed as:
! ( (interpreter >> std::ws).eof() )
That line is from the original, classic, correct idiom. The defect that I had
introduced was on the first line here:
else if(!(interpreter >> std::ws))
{
err << "Trailing whitespace remains ";
}
else if(!interpreter.eof())
{
err << "Unconverted data remains ";
}
whose operator!() does (inappropriately) test the state of the stream.