When I read all data from a stream, but make no attempt to read past its end, the stream's EOF is not set. That's how C++ streams work, right? It's the reason this works:
#include <sstream>
#include <cassert>
char buf[255];
int main()
{
std::stringstream ss("abcdef");
ss.read(buf, 6);
assert(!ss.eof());
assert(ss.tellg() == 6);
}
However, if instead of read()
ing data I ignore()
it, EOF is set:
#include <sstream>
#include <cassert>
int main()
{
std::stringstream ss("abcdef");
ss.ignore(6);
assert(!ss.eof()); // <-- FAILS
assert(ss.tellg() == 6); // <-- FAILS
}
This is on GCC 4.8 and GCC trunk (Coliru).
It also has the unfortunate side-effect of making tellg()
return -1
(because that's what tellg()
does), which is annoying for what I'm doing.
Is this standard-mandated? If so, which passage and why? Why would ignore()
attempt to read more than I told it to?
I can't find any reason for this behaviour on cppreference's ignore()
page. I can probably .seekg(6, std::ios::cur)
instead, right? But I'd still like to know what's going on.
I think this is a libstdc++ bug (42875, h/t NathanOliver). The requirements on ignore()
in [istream.unformatted] are:
Characters are extracted until any of the following occurs:
—n != numeric_limits<streamsize>::max()
(18.3.2) andn
characters have been extracted so far
— end-of-file occurs on the input sequence (in which case the function callssetstate(eofbit)
, which may throwios_base::failure
(27.5.5.4));
—traits::eq_int_type(traits::to_int_type(c), delim)
for the next available input character c (in which case c is extracted).
Remarks: The last condition will never occur iftraits::eq_int_type(delim, traits::eof())
.
So we have two conditions (the last is ignored) - we either read n
characters, or at some point we hit end-of-file in which case we set the eofbit
. But, we are able to read n
characters from the stream in this case (there are in fact 6 characters in your stream), so we will not hit end-of-file on the input sequence.
In libc++, eof()
is not set and tellg()
does return 6.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With