stream と NULL の比較
ファイルを読み込むプログラムで、こんなコードを提出された。
#include <fstream> #include <iostream> int main(int ac, char **av){ if (ac != 2) return 0; std::ifstream ifs(av[1]); if (ifs == NULL) std::cerr << "cannot open" << std::endl; else std::clog << "open file: " << av[1] << std::endl; // 続く }
普通、C++ではストリームが正常かどうかの判別は以下のようにするよね。
if (!ifs) std::cerr << "cannot open" << std::endl; else std::clog << "open file: " << av[1] << std::endl;
提出した人は、どっかで先のようなコードを見たというのだが、さて、ストリームとNULLを比較してもよいのだろうか?まず、ストリーム ifs はポインタでなく実体だから、NULLとの比較は意味的には間違っているのでは?しかしながら、g++ においてこのコードは警告オプションを付けても何の警告もなく通る!
明らかに警告が出そうなのに、何もでないカラクリは以下のような理由によると思った。
- C++ では NULL はマクロで 0 と定義されている(コンパイラによるけど)。
- ストリームには bool 型への変換演算子があるから bool 型の値(メンバ関数 fail() の逆の値)に変換される。
- int 型に暗黙の型変換
- 何の問題もなく比較可能
でも違った。手元の gcc4 では NULL はちゃんとポインタになってる。もちろん、NULLと整数型を比較すると警告が出る。
ストリームのどこかにポインタ型への変換演算子が隠されているんだろうか?全然解らん…