関数・クラステンプレートの明示的なインスタンス化 (具体化) (explicit instantiation of a function/class template)
いつもどこに書かれているかわからなくなるので、メモ。
関数やクラスのテンプレートは、常に使われるソースといっしょに置いておかないと、困る。つまり、テンプレートをモジュールわけして、別のソースにすることは通常できない。なぜなら、コンパイラはそのモジュールをコンパイルするときに、具体的に何の型を生成する必要があるかがわからないため、結局なにも生成してくれない。
したがって、通常は関数テンプレートの実装を丸ごとヘッダファイル化することが行われる (Effective C++ 3rd § 30)。これは分割コンパイル (separate compilation model) をしたい人にはとてもとても嫌なものだが、しょうがない。なお、このために、完全に同じ宣言は重複が許されている。
規格では export
キーワードによって、外部でインスタンス化されることを指定する方法が規定されているのだが、コンパイラの実装の難しさなどから、なかったことにされつつある。
それでも、分割しておきたい人は、あらかじめ使いたい型で明示的にインスタンス化しておくということを行う。これはこれであれだけど。
- 35.13 How can I avoid linker errors with my template functions?
- 35.15 How can I avoid linker errors with my template classes?
クラステンプレートの具体化の例
// テンプレートの定義 template<class T> class A { ... }; // int で具体化 template class A<int>; // template の後ろではなくて、変数名の後に型を書く
関数テンプレートの具体化の例
完全なシグネチャを作る必要があるので、少々面倒。
template<class T> T f(int x, double y, T z); // float で具体化 template float f<float>(int x, double y, float z); // すべての引数の型(引数の名前は任意)を書く。