Объект С++ Ifstream равен nullptr, но это не указатель?

Я пытался запустить тестовую программу при сбоях при открытии файла с помощью ifstream. Код ниже: -

#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;
}

Выход: -

false
true

Если ifs не является pointer, то как оно равно nullptr?

Ответы

Ответ 1

До С++ 11 потоки С++ неявно конвертируются в void*. Результат будет NULL, если поток не находится в состоянии без ошибок и что-то еще, если оно есть. Поэтому ifs == NULL (не должен работать с nullptr, см. Ниже) найдет и использует это преобразование, и поскольку ваше имя файла было неправильным, сравнение даст true.

В С++ 11 это было изменено на явное преобразование в bool, причем false указывает на ошибку и true хороший поток, потому что преобразование void* допускало слишком много бессмысленного кода, например ваш пример. Действительно, текущий компилятор в режиме С++ 11 или С++ 14 отклонит ваш фрагмент, вживую. Поскольку ваш код, по-видимому, не менее С++ 11, ваш компилятор не согласен, приняв его.

Эти преобразования допускают и предназначены для проверки ошибок следующим образом:

if ( !(ifs >> data) )
    std::cout << "Reading data failed.";

или, аналогично вашему примеру:

std::ifstream ifs ("wrong_filename.txt");
if (!ifs)
    std::cout << "Could not open file.";

Забавный факт дня: вы также можете использовать это для чистого цикла над файлом, например:

for (std::string line; std::getline(ifs, line);) {
    // Process line
}