またしても VC++ 6 のワナにハメられてしまった。 今回は、次のような関数テンプレートを定義し、
template<int N> void foo()
{
cout << N << endl;
}
次のような呼び出しを行った。
foo<1>(); foo<2>();
当然、"1" と "2" が表示されることを期待したわけだが、結果は何と両方とも "2"。
どうやら VC6 では、 テンプレート引数だけを変えて関数テンプレートのインスタンスを複数作ることができないらしい。 こんな中途半端なことをされるくらいなら、いっそコンパイルエラーになって欲しかった。 そのほうがすぐに別のやり方に書き直せるし、不可解なバグに悩まずにすむ。
ちなみに、上の問題を回避するには、ファンクタ (関数オブジェクト) を使うのが常套手段。
template<int N> class FunctorFoo {
public:
void operator()()
{
cout << N << endl;
}
};
を定義しておき、
FunctorFoo<1>()(); FunctorFoo<2>()();
で呼び出す。これを見て、 「いちいちコンストラクタを呼んでオブジェクトを生成してから operator() を呼び出すなんて、すっごく処理が遅くなりそう」とか思った人は、もう一回 勉強しなおしましょう。上のコードは最適化によってインライン展開されることが期待できるので、 実は、最初の (inline の付いていない) 関数テンプレート版より高速になりうるのです。
だったら、最初から素直にファンクタにしとけって? いやぁ、それは言わないお約束♥
その後、VC7 で試したところ、上記のバグは修正されていた。 VS .NET2003 だと、ひょっとしてもっと標準規格への準拠度が上がってたりするのかしらん?
初出: 2003年5月25日