名前空間に関する事故
私の分野では,ns-2 というシミュレータを使って性能評価をしたりします. 今回は,そのns-2のソースコードに手を加えていたときの話.
mapを使いたくて,#include<map>と書いたのですが, インクルードしただけで突然次のようなコンパイルエラーが現れました.
/usr/lib/gcc/i386-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/stl_algo base.h: In function `const _Tp& std::max(const _Tp&, const _Tp&) [with _Tp = Tra cedInt]': tcp/tcp-fs.cc:68: instantiated from here /usr/lib/gcc/i386-redhat-linux/3.4.5/../../../../include/c++/3.4.5/bits/stl_algo base.h:177: error: no match for 'operator<' in '__a < __b'
不思議に思い,エラーの元となったソースファイルを開いてみると,問題となっているのは maxseq_ = max(maxseq_, highest_ack_); という記述のようです. これは,非常に嫌な予感がします.using namespace std;の記述もないのに, 名前空間指定なしでコールされているmax()関数.さらに追ってみると, やはりといった感じで原因を突き止めることができました. 原因はtemplate.hというヘッダファイルにある以下の定義でした.
inline int max(int a, int b)
{
return a < b ? b : a;
}
STLのalgorithmで提供されているものと同名の関数がグローバル名前空間に定義されていたことで, mapと一緒にalgorithmがインクルードされた際におかしくなってしまったのだと思われます. これに加えて,明示的なキャストを怠ったことも災いして,コンパイルエラーが発生してしまったようです (highest_ack_は,TracedIntというns-2で独自に定義された型の変数で,template.hには, この型を引数とするmax()関数は定義されていない).
そういった訳で,今回の事例で得られた教訓.
- C/C++標準ライブラリ位は,同名の関数が存在してないか一通り調べましょう.
- 調べきれないのなら,名前空間を定義してその中で定義するようにしましょう.
- キャストはサボらずに明示的に行いましょう.
ns-2もひどいな,と感じる部分が多々存在します.