Consider the following code snippet:
#include <iostream>
#include <sstream>
int main()
{
std::stringstream ss;
ss << "12345";
unsigned short s;
ss >> s;
ss << "foo";
std::cout << std::boolalpha
<< "\nss.eof() = " << ss.eof()
<< "\nss.good() = " << ss.good()
<< "\nss.bad() = " << ss.bad()
<< "\nss.fail() = " << ss.fail()
<< "\nss.str() = " << ss.str();
}
clang++ trunk prints the following result:
ss.eof() = true ss.good() = false ss.bad() = false ss.fail() = false ss.str() = 12345
on wandbox
g++ trunk prints the following result:
ss.eof() = true ss.good() = false ss.bad() = false ss.fail() = true ss.str() = 12345
on wandbox
As you can see, the value of ss.fail()
is different between the two compilers. What does the Standard say regarding the behavior of std::stringstream
in this case? Is it implementation-defined to set failbit
/badbit
when writing to a stream that has already been consumed?
Gcc is correct. std::stringstream
inherits from std::basic_ostream
, and according to the behavior of operator<<(std::basic_ostream)
(which is invoked from ss << "foo";
),
Effects: Behaves like a formatted inserter (as described in [ostream.formatted.reqmts]) of out.
And from §30.7.5.2.1/1 Common requirements [ostream.formatted.reqmts]:
(emphasis mine)
Each formatted output function begins execution by constructing an object of class sentry. If this object returns true when converted to a value of type bool, the function endeavors to generate the requested output. If the generation fails, then the formatted output function does setstate(ios_base::failbit), which might throw an exception.
And §30.7.5.1.3 Class basic_ostream::sentry [ostream::sentry]:
If os.good() is nonzero, prepares for formatted or unformatted output. If os.tie() is not a null pointer, calls os.tie()->flush().
If, after any preparation is completed, os.good() is true, ok_ == true otherwise, ok_ == false. During preparation, the constructor may call setstate(failbit) (which may throw ios_base::failure ([iostate.flags]))
And §30.5.5.4 basic_ios flags functions [iostate.flags]:
iostate rdstate() const;
Returns: The error state of the stream buffer.bool good() const;
Returns: rdstate() == 0bool eof() const;
Returns: true if eofbit is set in rdstate().
eofbit
has been set in this case, then std::basic_ios::good
returns nonzero and causes writing failed (as the result showed), then failbit
should be set.
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