C++ stream extraction operator overloading -
this question philosophy (canonical design) of user-written c++ input stream extraction operators (>>).
assume on entry >> operator implementation (for user-written class), eof flag set input stream.
should user-written extraction operator (>>)
- set failure flag (because no instance of desired object can found)
- should return caller eof flag still set.
if second approach used, implies caller must check eof flag before attempt made invoke >> operator. reason >> operator might extract instance of desired class , set eof flag.
the original code follows. based on comments below, code appears wrong. if eof set on input, extraction operator return eof still set. appears if eof set, bad , fail not set, extraction of string should done set fail bit. of course, fail bit can set directly.
/* implement c/c++ >> (stream input) operator non-member function */ std::istream &operator>>(std::istream& is, decnumber &val) { deccontext context{deccontext::definit}; uint32_t status; /* true value below prevents whitespace being skipped */ std::istream::sentry s(is, true); std::string instr; /* check if input stream in state. return caller if input stremm not in state. caller must handle condition. */ if(!s) return is; /* string input stream. string converted decnumber below. return caller if step causes stream related errors. note reaching end of input not stream related error here. decimal number might absolute last thing in stream. */ >> instr; if (is.bad() || is.fail()) return is; /* try convert string decnumber using default context value */ decnumberfromstring(val.getdecval(), instr.c_str(), context.getdeccont()); status = context.deccontextgetstatus(); /* remove few status bits don't care */ status &= ~(dec_inexact + dec_rounded); if (status) is.setstate(std::ios_base::failbit); return is; }
you should implement solution 1.
when in doubt, @ what's being done. can see below, fail bit being set if try read stream in eof state.
note eof not way fail though. try setting std::string vals = "52 43 a"; in code below.
failbit should set if for reason, operator>> doesn't stream value. eof 1 of reasons.
#include <sstream> #include <iostream> #include <string> void print_stream (std::istream & print_me, int const & i) { std::cout << "i: " << << "\n"; std::ios_base::iostate bits = print_me.rdstate(); std::cout << "good: " << (bits & std::ios_base::goodbit) << ", bad: " << (bits & std::ios_base::badbit) << ", fail: " << (bits & std::ios_base::failbit) << ", eof: " << (bits & std::ios_base::eofbit) << "\n"; std::cout << "\n----------------------------\n\n"; } int main (void) { std::string vals = "52 43"; std::istringstream iss(vals); int i; iss >> i; print_stream (iss, i); iss >> i; print_stream (iss, i); iss >> i; print_stream (iss, i); iss >> i; print_stream (iss, i); return 0; } outputs
$ ./a.exe i: 52 good: 0, bad: 0, fail: 0, eof: 0 ---------------------------- i: 43 good: 0, bad: 0, fail: 0, eof: 2 ---------------------------- i: 43 good: 0, bad: 0, fail: 4, eof: 2 ---------------------------- i: 43 good: 0, bad: 0, fail: 4, eof: 2 ---------------------------- note typical read pattern loop variation of...
while (input >> var >> var2 >> var3) { // failbit not set. reads succeeded. // stuff } if need detect whether fail happened @ point during reading of multiple values yea, need little more sophisticated , testing like...
while (true) { if (input >> var) { // read first value if (input >> var2 >> var3) { // succesfully read values! // stuff } else { errorlog ("partial line read!"); break; } else { // nothing else read break; } }
Comments
Post a Comment