qt - C++ istream tellg()/fail() on eof: behavior change; work-around? -


i upgraded compiler gcc-4.4 gcc-4.8 , 1 project fails miserably stemming following (false) assumptions:

#include <sstream> #include <assert.h>  int main() {     using namespace std;     istringstream iscan;     int num;      //iscan.unsetf(std::ios::skipws);     iscan.str("5678");     iscan >> num;     assert(iscan.tellg() == istringstream::pos_type(4));     assert(!iscan.fail());     assert(!iscan.good());     assert(iscan.eof());     assert(num == 5678);     assert(false && "we passed above assertions.");     return 0; } 

on gcc-4.4, relevant assertions pass. on gcc-4.8, tellg() returns -1 , and fail() returns !false, apparently since hit eof.

my target mingw 32-bit shipped qt 5.1 (gcc-4.8).

questions:

  • is old behavior in error, per n3168 or other? (which other?)
  • is there global, reliable, language-independent work-around? (i'm guessing not.)
  • is there global, reliable, gcc work-around spans versions?
  • even when above unsetf(skipws), still doesn't work on gcc-4.8. isn't that incorrect behavior?

further, various online compilers give different behavior. function of lib?

  • compileonline, claims gcc-4.7.2, allows though other sources behavior changed in 4.6.
  • stack-crooked, gcc-4.8, shows new behavior, , unsetf(skipws) seems have no effect.
  • codepad allows it. can't tell version.

other similar not duplicate questions:

the body of code, these assumptions running through all, large.

update: here's key part of answer, should work across versions, compilers:

// istream::tellg() unreliable @ eof(): works w/gcc-4.4, doesn't w/gcc-4.8. #include <sstream> #include <assert.h>  using namespace std; typedef istream::pos_type   pos_type;  pos_type reliable_tellg(istream &iscan)     {     bool waseof = iscan.eof();     if (waseof)         iscan.clear(iscan.rdstate() & ~ios::eofbit); // tellg() works.     pos_type r = iscan.tellg();     if (waseof)         iscan.clear(iscan.rdstate() | ios::eofbit); // restore it.     return r;     }   int main() {     istringstream iscan;     int num, n2;      //iscan.unsetf(std::ios::skipws);     iscan.str("5678");     assert(!iscan.eof() && !iscan.fail()); // pre-conditions.     assert(reliable_tellg(iscan) == pos_type(0));      iscan >> num;     assert(!iscan.fail());     assert(reliable_tellg(iscan) == pos_type(4));     assert(iscan.eof());     assert(reliable_tellg(iscan) == pos_type(4)); // previous calls don't bungle it.     assert(num == 5678);      iscan >> n2; // @ eof(), should fail.     assert(iscan.fail());     assert(reliable_tellg(iscan) == pos_type(-1)); // expected on fail()     assert(iscan.eof());      assert(false && "we passed above assertions.");     return 0; } 

the behavior seem expect wrong. both c++11 , c++03 start description of tellg "behaves unformatted input function[...]". "unformatted input function" starts constructing sentry object, , fail, doing nothing , returning failure status, if sentry object converts false. , sentry object convert false if eofbit set.

the standard less clear whether reading number sets eofbit, (with information spread out on several different sections). basically, when inputting numeric value, stream (actually, num_get facet) must read 1 character ahead, in order know number ends. in case, see end of file when occurs, , set eofbit. first assert fail conforming implementation.

one consider defect in standard, or unintentional. it's easy imagine implementations doing sensible thing (which seem expect), perhaps because original implementors didn't realize full implications in standard (or unconsciously read thought should read). guess case g++, , when realized behavior non-conformant, fixed it.

as work-arounds... i'm not sure real problem is, you're trying work around. think if clear error bits before tellg, should work. (of course, iscan.good() true, , iscan.eof() false. can matter?) sure check extraction succeeded before clear status.


Comments

Popular posts from this blog

Unable to remove the www from url on https using .htaccess -