I was trying a test program on failures of opening a file using ifstream
. The code is below :-
#include <iostream>
#include <fstream>
#include <type_traits>
using namespace std;
int main()
{
ifstream ifs ("wrong_filename.txt");
cout << boolalpha;
cout << is_pointer<decltype(ifs)>::value <<"\n";
cout << (ifs==nullptr);
return 0;
}
Output is :-
false
true
If ifs
is not a pointer
, then how does it equal to nullptr
?
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
}
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