Until C++11, C++ streams are implicitly convertible to void*
. The result will be NULL
if the stream is not in an errorless state and something else if it is. So ifs == NULL
(should not work with nullptr
, see below) will find and use that conversion, and since your filename was wrong, the comparison will yield true.
In C++11, this was changed to an explicit conversion to bool
, with false
indicating an error and true
a good stream, because the void*
conversion allowed too much nonsensical code, such as your example. Indeed, a current compiler in C++11 or C++14 mode will reject your snippet, live. Since your code is obviously at least C++11, your compiler is non-conforming by accepting it.
Those conversions allow and are intended for error checks like this:
if ( !(ifs >> data) )
std::cout << "Reading data failed.";
or, analogous to your example:
std::ifstream ifs ("wrong_filename.txt");
if (!ifs)
std::cout << "Could not open file.";
Fun fact of the day: You can also use this to cleanly loop over a file, e.g.:
for (std::string line; std::getline(ifs, line);) {
// Process line
}