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
true
if an error has occurred on the associated stream. Specifically, returnstrue
if 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