テンプレートの定義・実装について

[戻る]
kuma 2004/01/15(木) 00:19:28
はじめまして。 テンプレートを最近弄り始めたのですが
テンプレートクラスの定義と実装が別々のファイルであった場合
ビルドしようとすると「外部シンボル****は未解決」とエラーが出てしまいます。
定義と実装を同じファイルにしておくと問題なくビルドできました。

これは定義と実装は、同じファイルでしないといけないのでしょうか?
それとも、単にソースの書き方が悪いだけで、別のファイルに書く方法が
あるのでしょうか?
もしよろしければ、ご回答お願いします。

--- 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;
  ...
}

kuma 2004/01/15(木) 00:26:14
すみません。 環境を書き忘れました。

WinXP HomeEdition + VC++6.0 EnterpriseEditionです。

2004/01/15(木) 01:58:24
私に理解ではテンプレートは現実のコードを生成するための雛型(型枠)ですから、
コンパイラーが 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++のソースコードであると期待しますからテンプレート
の実装部しか記述しないのでしたら不適切かもしれません

てつや 2004/01/15(木) 10:31:56
>テンプレートクラスの定義と実装が別々のファイルであった場合
>ビルドしようとすると「外部シンボル****は未解決」とエラーが出てしまいます。
島さんの仰っている方法を取るか、実装を定義の中に書きましょう。

てつや 2004/01/15(木) 10:43:10
>私に理解ではテンプレートは現実のコードを生成するための雛型(型枠)ですから、
>コンパイラーが main.cpp をコンパイルする時に header.h の知識だけでは不十分
>だと思いますが、これはお分かりですね
>そして、 temp.cpp は現実のコードではなく、雛型なので temp.cpp だけでは
>コンパイラーはオブジェクトを生成することはできません(T に関する知識が
>足りない)から temp.obj が出来る訳はないので temp.cpp が単独でコンパイルの
>対象になることもありません
私は↓を見て、ただ単にVCが対応していないだけと認識しています
http://www.mtakahashi.com/old/06600.html#06578

2004/01/15(木) 11:12:10
てつやさんへ

提示しているソース中では export キーワードを使ってないので少しずれていると思います
  私が言いたかったのは提示したソースからは header.h と temp.cpp との関連が
  コンパイラーには理解できないということです
http://www.tietew.jp/cppll/archive/1395 の議論を参照なさって下さい

てつや 2004/01/15(木) 12:45:17
大変興味深い内容をどうもありがとうございます。

とりあえず、VCがexportってのをサポートしたら分割してコンパイルできるようになるんだ
ぐらいの認識だったので大変勉強になりました

kuma 2004/01/15(木) 19:30:29
なるほど。
・宣言と実装を別々に書く方法もあるが、テンプレートのexportを
 サポートしていないコンパイラがほとんどであること
・安全にコンパイルさせたいなら、宣言と実装は同じファイルに書く
 もしくは別のヘッダファイルに記述し、共にインクルードすること
ということですね。

島さん、わかりやすい説明ありがとうございました。
てつやさん、面白い記事の提供ありがとうございました。

kuma 2004/01/15(木) 19:30:21
[[解決]]
解決チェックを入れ忘れてました。

古いスレッドには追加発言できません。