class template の中で配列の値初期化が出来ない [gcc 4.6 20101106]
class template の中で int * の値初期化をしようと思った.ところが,
#include <iostream> template <typename T> class A { public: A (size_t n) : _dummy () { int * p = new int[n] (); // compile error for (size_t i = 0; i < n; ++i) std::cerr << i << ": " << p[i] << std::endl; delete [] p; } private: T _dummy; }; int main () { A <int> a (16); return 0; }
とすると, 4.6.0 20101106 (macports) で
> g++ test.cc test.cc: In constructor 'A<T>::A(size_t)': test.cc:7:27: internal compiler error: in build_value_init, at cp/init.c:299 Please submit a full bug report, with preprocessed source if appropriate. See <http://gcc.gnu.org/bugs.html> for instructions.
と怒られる.gcc 4.5 以前は ok, 4.6 でも class template の中でなければ ok.何故だ・・・.もちろん,
#include <iostream> int main () { size_t n = 16; int * p = new int[n] (); for (size_t i = 0; i < n ; ++i) std::cerr << i << ": " << p[i] << std::endl; }
なら ok.gcc 4.6 20101106 のソースを読んだら,template の宣言中だと assert で落ちるようになっていた(そのままだよ; gcc 4.5.1 のソース中にはない).
/* The AGGR_INIT_EXPR tweaking below breaks in templates. */
gcc_assert (!processing_template_decl);
(前略) 2010-08-19 XXXXX XXXXXXX <xxxxx@xxxxxx.xxx> (中略) PR c++/45315 * init.c (build_new_1): Don't use build_value_init in a template. (build_value_init): Make sure we don't. (後略)
Bug 45315 に対する patch の副作用かな(`new T[n] ()' としてインスタンス化されるまで評価を遅延するとコンパイルできる).gcc 4.4/4.5 にも merge されているようだ.c++ の仕様はごく一部しか把握していないので regression なのかどうか判断できない.値初期化を諦めて,std::memset / std::fill_n するしかないか.
そう言えば,今までも数回,gcc が bug report しろみたいに宣うことがあったな(-O2 以上で挙動が不審になることもあった).これからはメモすることにしよう.
[追記; 12/8] 11/25 付けで本家に bug 登録されていた.
bug fix 待ち. 2011/01/11 付けでパッチが入った模様.よかったよかった.gcc 4.6 (20110115) にて修正を確認.