This is the mail archive of the
libstdc++@sourceware.cygnus.com
mailing list for the libstdc++ project.
Re: Funniness with operator>> (istream&, string&)
- To: libstdc++ at sourceware dot cygnus dot com, austern at sgi dot com
- Subject: Re: Funniness with operator>> (istream&, string&)
- From: Benjamin Kosnik <bkoz at cygnus dot com>
- Date: Mon, 24 Jan 2000 22:15:57 -0800 (PST)
> When i run this test, it does not properly sense the EOF condition,
> but instead goes into an infinite loop:
Yeah. There was some discussion of this change to istream::sentry here,
read the whole thread.
http://sourceware.cygnus.com/ml/libstdc++/2000-q1/msg00004.html
You'll need to specifially test for istream.good(), not the boolean
operator, which only tests for fail().
> The sentry class used to set failbit as well on eof.
>
> So i was set to write this up as a bug report.
> But after studying the C++ standard for a while, i do not find support
> for the assertion that this is a bug; in fact, the infinite loop seems
> to be the specified behavior.
(Welcome to my world of pain?)
Look at the defect comments surrounding this change:
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
//195. Should basic_istream::sentry's constructor ever set eofbit?
else
__in.setstate(ios_base::eofbit);
#endif
This was initally brought up because istream::sentry didn't explicitly set
eofbit (although it was implied). The proposed change set eofbit |
failbit, which then introduced an inconsistency between hitting eof as one
is clearing whitespace in the sentry ctor (which would then set
eofbit|failbit and cause operator bool() to fail) versus hitting eof as
one is doing formatted/unformatted extraction (which would then set just
eofbit, allowing operator bool() to pass).
perhaps what really should be done is have
bool basic_ios::operator!()
basic_ios::void*() const
work with good() instead of fail().
This issue was brought up with the library working group. It seems to have
stalled though, so I don't know the current status.
I would like to make the setting of failbit consistent. I believe the CVS
sources reflect the most consistent behavior.
> If i look at the description of operator>> (istream&, string)
> (21.3.7.9), i don't see anything that tells me that that failbit _should_
> be set in this case. If i compare this with the description of similar
> functions -- for example getline<charT> (istream&, string&, charT)
> (21.3.7.9) or operator>> (istream&, charT*) (27.6.1.2.3) or
> istream::get (char_type*, streamsize, char_type) (26.6.1.3) -- i see
> that the descriptions of those functions all include a statement to the
> effect that `If the functions extracts no characters, it calls
> setstate(failbit)'. However, in the case of operator>> (istream&, string&),
> this requirement is conspicuously absent.
This makes sense. I believe it should set failbit here too. This is a
separate issue from istream::sentry::sentry() setting failbit though.
> So, i'm wondering, is this an error in the standard, or is this
> a deliberate decision?
another mistake.
> I don't see any mention of this in the
> library issues list. On the other hand, i can't think of any reason
> why the behavior specified in the standard (i.e., not setting failbit
> in the case where no characters were extracted) would be desireable.
> In fact, i can think of several reasons why it's not a good thing:
>
> - The semantics of failbit are described as including (table 85)
> `an input operation failed to read the expected characters'.
> This is exactly what's happening in this case -- but failbit
> is not getting set.
right
>
> - One could perhaps argue that the intended semantics of
> operator>> (istream&, string&) at EOF is to read
> an empty string and return success. However, the specification
> of this operator does not ensure the first part of this: if no characters
> are extracted, the string argument to the operator is untouched.
> So, old data will be seen in the string, rather than the empty string.
I think this is not intuitive.
> - One might say that for using this operator, one needs to use
> good() or !eof() on the stream, rather than testing failbit.
> But that means that it is impossible to use istream_iterator<stream>,
> since the end-of-sequence testing for an istream_iterator is
> specified as being a test of failbit.
see above. .
-benjamin