Преобразование false в тип указателя void *?
Может кто-нибудь объяснить мне, что здесь происходит?
У меня был этот код:
#include <fstream>
#include <string>
#include <iostream>
int main(){
std::ifstream file("test.txt");
std::string x;
while (true) {
if (!(file >> x)) return 0;
std::cout << x << "\n";
}
}
... компилирует отлично, делает то, что он должен делать, пока не проблема. Иногда мне так не нравится !
, потому что его можно легко пропустить, поэтому я заменил if
на
if ((file >> x)==false) return 0;
.. и вдруг мой компилятор (gcc 4.8.5) жалуется на предупреждение:
warning: converting ‘false’ to pointer type ‘void*’ [-Wconversion-null]
if ((file >> x)==false) return 0;
и именно здесь я начинаю озадачиваться. Откуда приходит void*
? Не возвращает >>
ссылку, которая должна быть отправлена на bool
? Почему false
преобразован в void*
? Почему не срабатывает такое же предупреждение, когда я явно не пишу false
?
Из любопытства я также пробовал это:
if ((file>>x)==true) return 0;
который вызывает бурю ошибок, начиная с
error: no match for ‘operator==’ (operand types are ‘std::basic_istream<char>’ and ‘bool’)
if ((file>>x)==true) return 0;
^
и теперь я полностью потерян. Как false
отличается от bool
чем true
? Конечно, разные значения, но я всегда думал, что true
и false
имеют один и тот же тип.
Ответы
Ответ 1
Вспомним, что С++ имеет перегрузки оператора. В частности, std::basic_istream
перегружает operator!
.
Увы, не существует принуждения, что перегрузки операторов семантически согласованы, поэтому для ==
нет перегрузки между istream
и a bool
. Таким образом, сравнение с true
не выполняется. Однако компилятору также разрешено применять неявные преобразования, чтобы скомпилировать выражение - в этом случае false
может быть неявно преобразован в нулевой указатель, а basic_istream
имеет перегрузка operator void*
(хотя, по-видимому, это было заменено на operator bool
на С++ 11 - для исправления несогласованности).