template 関数で同じ関数が複数定義される場合
c++ で template関数を使う場合に特殊化により関数を制作する時に、template関数が定義されているヘッダーを複数のソースに使う場合に同じ関数が二度生成されてしまいますが、これはどう解決すればよいですか?
例えば次のような場合です。
// header_temp.hpp
template <typename T>
void foo(T a) {
cout << a << endl;
}
// source_1.cpp
#include "header_temp.hpp"
#include "header_class_alice.hpp" // class Aliceが定義されている
void hoge() {
foo<Alice>(10);
}
// source_2.cpp
#include "header_temp.hpp"
#include "header_class_alice.hpp"
void fuga() {
foo<Alice>(10);
}
上記の場合はsource_1.cppのコンパイルの際に関数foo<Alice>
が生成され、source_2.cppをコンパイルする際にまた関数foo<Alice>
が生成されます。今、関数foo<Alice>
はinlineに定義されていないので、厳密には同じ関数が二度定義されています。これはリンクの際に問題を起こします。この解決のためにはソースの内一つでtemplate void foo<Alice>(Alice)
して、残りのソースではextern void foo<Alice>(Alice);
するか、template fooの定義をそもそもinlineにすることですが、関数が大きくなるとinlineにしてソースごとに関数の定義をしてしまうのはバイナリーサイズの観点で浪費があると考えます(完全に同じ関数を二回定義しているので)。
template関数自体は共有ライブラリーみたいにはできないので(その特殊化はできますが)、このような問題は必ず生じかねないとは思いますが、もし上記のtemplate, externを使った方法以外にプログラムバイナリーでtemplateにより生成された特殊化関数void foo<Alice>(Alice)
が一つだけ存在する様にするにはどうすればよいでしょうか?
そしてこのことによると、stlのvectorなどのcontainerは複数のソースでvector<Alice>
で定義されたcontainerが生成された場合に、ソースごとにvector<Alice>::push_back
などのメソッドを生成することになりますが、そうでしょうか?