Take this toy code:
#include <iostream>
#include <fstream>
int main() {
std::ifstream is;
// perform read
// ...
if (!is) // works
std::cout << "fail";
if( is == false) // error C2678
std::cout << "fail";
return 0;
}
You'd get the following counter-intuitive results: if(!is)
compiles, and if(is==false)
gives
error C2678: binary '==': no operator found which takes a left-hand operand of type 'std::ifstream' (or there is no acceptable conversion)
(for VS2015 - similar errors in gcc and clang).
The standard says (according to this answer):
Valid C++ 2003 code that relies on implicit boolean conversions will fail to compile with this International Standard. Such conversions occur in the following conditions:
passing a value to a function that takes an argument of type bool;
using operator== to compare to false or true;
returning a value from a function with a return type of bool;
initializing members of type bool via aggregate initialization;
initializing a const bool& which would bind to a temporary.
As far as I can tell if(is==false)
is explicitly required to fail, but how come if(!is)
doesn't? Doesn't it qualify as an 'implicit boolean conversion'?
Was this conversion-to-bool deliberately omitted from the cases listed in the standard? Perhaps it's an unintentional omission?
Edit: This code fails just as well:
int main() {
std::ifstream is;
// perform read
// ...
if (is) // works
std::cout << "success";
if( is == true) // error C2678
std::cout << "success";
return 0;
}
And here the presence of operator!() is irrelevant.
std::ifstream
's inherited operator bool
is marked explicit
:
explicit operator bool() const;
(2) (since C++11)
What this means is that there is no implicit conversion to bool, i.e. all of those expressions fail:
bool result = is; // fails
bool b = is == true; // fails
if (is == false); // fails
while (is == false); // fails
If you wonder why if (is)
and similar statements compile, that is because there are special rules for if
, while
, and the like for conversions: The explicit
keyword is ignored!
if (is); // ok
while (is) // ok
bool b = static_cast<bool>(is); // ok
Note that the last case compiles because you are explicitly wanting a bool.
Technically, !is
would work fine, as you explicitly want a bool, but std::ifstream
has a inherited operator!
, so that operator is called instead of the default operator!
which operates on bools:
if (!is); // ok
bool b = !is; // ok
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