C++ テンプレート関数をソース・ファイルに書く

前提

まだ完全にはわからない

Tが汎用の場合

std::vector<T>などのTに何でも入れられることを前提にしてつくられているクラスはヘッダに書くしかないと思う。

Tが一部の型のみの場合

この場合はソースファイルにかける。

ここでは文字列の長さをを返す関数でchar*とwchar_t*をとるGetStringLength()を考える。

ヘッダ

最初のテンプレート関数は汎用のTを受け取る。もしテンプレート関数が実体化されたときはstatic_assertでエラーになるようにしている(sizeof(T)は決して0にならない。falseを指定してしまうと実体化しなくてもエラーになってしまう(コンパイラ依存))。char*とwchar_t*で特殊化するので、それ以外のポインタで呼ばれたときに実体化される。

次の2つは特殊化の宣言。定義はソースに書く。
次の2つは特殊化が実体化されるときの場所の指定。externでどこかにそれがあることを示している。

ソース

最初の2つは特殊化の定義。
次の2つは特殊化が定義されるときここに実体化されることを意味する。

main.cpp

今回の場合は実装がほぼないのでテンプレートにする意味があんまりないが、2つの実装がほぼ同じで、一部だけ書き換えたいときは汎用Tの方に実装を書くこともできる。その場合にこのテンプレートを使うこともできる。

Tが一部の型のみの場合(バージョン2)

ヘッダー

ソース&main.cpp

ソース:https://github.com/ambiesoft/blogprogs/tree/master/6038

考察

テンプレート関数の定義をソース・ファイルに書くと、他のソース・ファイルからは見ることができないのでリンカーでつなげることになる。よって鉤括弧なしのtemplateは実装を実体化し外部に公開して他のソース・ファイルから見えるようにしているのだと思われる。

鉤括弧ありのテンプレートはあくまでコンパイルフェーズで解決するものであり、宣言だけのテンプレートを実体化しても宣言だけになり、それがリンクされることもないのだと思われる。

Leave a Reply

Your email address will not be published. Required fields are marked *

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)