はじめまして。 テンプレートを最近弄り始めたのですが
テンプレートクラスの定義と実装が別々のファイルであった場合
ビルドしようとすると「外部シンボル****は未解決」とエラーが出てしまいます。
定義と実装を同じファイルにしておくと問題なくビルドできました。
これは定義と実装は、同じファイルでしないといけないのでしょうか?
それとも、単にソースの書き方が悪いだけで、別のファイルに書く方法が
あるのでしょうか?
もしよろしければ、ご回答お願いします。
--- header.h ---
template<class T> class A{
T value;
public:
A(void);
~A(void);
void set(T);
T get(void) const;
};
--- temp.cpp ---
#include header.h
template<class T> A<T>::A(void):value(0){}
template<class T> A<T>::~A(void){}
template<class T> void A<T>::set(T v){value = v;}
template<class T> T A<T>::get(void)const{return value;}
--- main.cpp ---
#include header.h
void main(void){
A<char> a;
...
}
すみません。 環境を書き忘れました。
WinXP HomeEdition + VC++6.0 EnterpriseEditionです。
私に理解ではテンプレートは現実のコードを生成するための雛型(型枠)ですから、
コンパイラーが main.cpp をコンパイルする時に header.h の知識だけでは不十分
だと思いますが、これはお分かりですね
そして、 temp.cpp は現実のコードではなく、雛型なので temp.cpp だけでは
コンパイラーはオブジェクトを生成することはできません(T に関する知識が
足りない)から temp.obj が出来る訳はないので temp.cpp が単独でコンパイルの
対象になることもありません
A<char> について現実のクラスを生成するためには header.h と temp.cpp との
両者の知識が必要になりますね
例えば
#include temp.cpp
int main (int /**/, char ** /**/) {
A<char> a;
...
return 0;
}
とでも書いていればコンパイラーはテンプレートから現実のコードが展開生成できる
かも知れません
ところで拡張子 cpp はC++のソースコードであると期待しますからテンプレート
の実装部しか記述しないのでしたら不適切かもしれません
>テンプレートクラスの定義と実装が別々のファイルであった場合
>ビルドしようとすると「外部シンボル****は未解決」とエラーが出てしまいます。
島さんの仰っている方法を取るか、実装を定義の中に書きましょう。
>私に理解ではテンプレートは現実のコードを生成するための雛型(型枠)ですから、
>コンパイラーが main.cpp をコンパイルする時に header.h の知識だけでは不十分
>だと思いますが、これはお分かりですね
>そして、 temp.cpp は現実のコードではなく、雛型なので temp.cpp だけでは
>コンパイラーはオブジェクトを生成することはできません(T に関する知識が
>足りない)から temp.obj が出来る訳はないので temp.cpp が単独でコンパイルの
>対象になることもありません
私は↓を見て、ただ単にVCが対応していないだけと認識しています
http://www.mtakahashi.com/old/06600.html#06578
てつやさんへ
提示しているソース中では export キーワードを使ってないので少しずれていると思います
私が言いたかったのは提示したソースからは header.h と temp.cpp との関連が
コンパイラーには理解できないということです
http://www.tietew.jp/cppll/archive/1395 の議論を参照なさって下さい
大変興味深い内容をどうもありがとうございます。
とりあえず、VCがexportってのをサポートしたら分割してコンパイルできるようになるんだ
ぐらいの認識だったので大変勉強になりました
解決チェックを入れ忘れてました。
なるほど。
・宣言と実装を別々に書く方法もあるが、テンプレートのexportを
サポートしていないコンパイラがほとんどであること
・安全にコンパイルさせたいなら、宣言と実装は同じファイルに書く
もしくは別のヘッダファイルに記述し、共にインクルードすること
ということですね。
島さん、わかりやすい説明ありがとうございました。
てつやさん、面白い記事の提供ありがとうございました。