lmi
[Top][All Lists]
Advanced

[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.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]