The following code compiles in Visual Studio 2008 but fails in Visual Studio 2013 and later.
std::string str("foo");
std::stringstream ss(str);
float f = 0;
if ((ss >> f) == false)
    std::cout << "Parse error\n";
The error message is
error C2678: binary '==' : no operator found which takes a left-hand operand of type 'std::basic_istream>' (or there is no acceptable conversion)
and is successfully fixed by changing as follows:
if (!(ss >> f))
    std::cout << "Parse error\n";
I'm not understanding this well. My question is, what operator or cast or maybe  ios flags are involved that allow the stream read to be evaluated as a boolean in the first place, and then why does the lack of an operator== break it? 
Two behaviors changed since C++11.
The behavior of std::basic_ios::operator bool changed.
operator void*() const;         (1) (until C++11)
explicit operator bool() const; (2) (since C++11)
Note since C++11 operator bool() is declared as explicit; but for if ((ss >> f) == false), ss (i.e. the return value of (ss >> f)) needs to be implicit converted to bool (to be compared with false), which is not allowed.
The definition of the null pointer constant changed.
Before C++11 operator void*() could be used and it's not explicit (before C++11 there's no such explicit user-defined conversion), and before C++11 the null pointer constant is defined as:
an integral constant expression rvalue of integer type that evaluates to zero (until C++11)
which means false could be used as a null pointer constant. So ss could be implicitly converted to void* and then compared with false (as the null pointer).
From C++11, the null pointer constant is defined as:
an integer literal with value zero, or a prvalue of type
std::nullptr_t(since C++11)
while false is not again; it's not an integer literal.
So, because of these two changes, if ((ss >> f) == false) won't work in C++11 and later.
On the other hand, if (!(ss >> f)) works fine because there's std::basic_ios::operator! (both before and after C++11) for it.
bool operator!() const;Returns
trueif an error has occurred on the associated stream. Specifically, returnstrueif badbit or failbit is set inrdstate().
BTW: Since C++11, even without std::basic_ios::operator!, explicit operator bool() const could also make if (!(ss >> f)) works well, because in the context of contextual conversion, explicit user-defined conversion is considered; i.e. ss could be contextually converted to bool for operators !.
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