2007-05-17
VisualC++でテンプレートをCPP側で実装できない件
結論
VisualC++コンパイラの仕様上、CPPには実装できない。
但し、明示的実体化を行うことで、実装可能。
例
TemplateClass.h:テンプレートのヘッダ
template <class T> class TemplateClass { // コンストラクタ TemplateClass(T* t); int getValue(); };
TemplateClass.cpp:テンプレートの実装
#include "TemplateClass.h" // コンストラクタ TemplateClass<T>::TemplateClass(T* t) { this->t = t; } int TemplateClass<T>::getValue() { t->getValue(); }
main.cpp
#include "TemplateClass.h" // テンプレート実体化の際のステータスに使用 class TestClass { int getValue() { return 100; } }; void main() { // テンプレート実体化 TemplateClass<TestClass> t = new TemplateClass(new TestClass()); // 100が出力される std::cout << t->getValue() << std::endl }
コンパイル時(すなわちコードの自動生成時に)以下のようなリンクエラーが発生する。
error LNK2019: 未解決の外部シンボル "public: int __thiscall TemplateClass<class TestClass>::getValue(void)" (?getValue@?$TemplateClass@VTestClass@@@QAEHXZ) が関数 _wmainで参照されました。
error LNK2019: 未解決の外部シンボル "public: int __thiscall TemplateClass<class TestClass>::TemplateClass(class TestClass *)" (??0?$TemplateClass@VTestClass@@@@QAE@PAVTestclass@@@Z) が関数 _wmainで参照されました。
fatal error LNK1120: 外部参照2が未解決です。
VC++がテンプレートについて、inclusion-modelという実体化を採用している為。
inclusion-modelとは、簡単に言うと、テンプレートの実装はヘッダーに書く。
CPPに実装を書いた場合、コンパイラはテンプレートの宣言を実体化できない。
それでもCPPに実装を書きたい場合は、テンプレートの実体をCPPにて明示する。
これを明示的実体化と言う。
明示的実体化の方法
TemplateClass.cpp
#include "TemplateClass.h" #include "TestClass.h" // コンストラクタ TemplateClass<T>::TemplateClass(T* t) { this->t = t; } int TemplateClass<T>::getValue() { t->getValue(); } // 実体化したいクラス(型)を指定する。 template class TemplateClass<TestClass>
これにより、ヘッダーにて実装を晒したくない場合に対応できる。
CPP側で実装し、明示的実体化をしておけば、特定の型以外の実体化を禁止できる。
(特定の型以外の実体化はコンパイル時にリンクエラーとなる)
但し、実体化するクラス(型)が固定されてしまうため、コードの柔軟性は低下する。
また、テンプレートを使用してのメタプログラミングには適用できない。
状況に応じて、ヘッダーで実装するか、明示的実体化を行うか決めるべし。
参考サイト
[vcpp 00029744]Re: templateクラスについて
そんな感じー。
- 177 http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&rls=GGLD,GGLD:2006-15,GGLD:ja&q=VC+型+T
- 137 http://www.google.co.jp/search?hl=ja&q=テンプレートクラス コンストラクタ&btnG=Google+検索&lr=lang_ja
- 137 http://www.google.co.jp/url?sa=t&rct=j&q=テンプレート クラス コンストラクタ エラー&source=web&cd=7
- 133 http://www.google.co.jp/search?q=テンプレートクラス&hl=ja&lr=lang_ja&client=firefox&rls=org.mozilla:ja:official&hs=GxO&start=20&sa=N
- 80 http://www.google.com/search?hl=ja&lr=lang_ja&ie=UTF-8&oe=UTF-8&q=C++/CLI+include&num=50
- 76 http://www.google.co.jp/search?hl=ja&client=firefox-a&rls=org.mozilla:ja:official&hs=ZyY&q=テンプレート cpp&btnG=検索&lr=lang_ja
- 71 http://www.google.co.jp/search?hl=ja&q=C+++テンプレート リンク エラー&btnG=Google+検索&lr=
- 70 http://www.google.co.jp/search?q=c+++テンプレート+実装&sourceid=navclient-ff&ie=UTF-8&rls=GGGL,GGGL:2006-38,GGGL:ja
- 66 http://www.google.co.jp/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&sqi=2&ved=0CCQQFjAA&url=http://d.hatena.ne.jp/kasei_san/20070517/p1&ei=lg9GT_ysIMyWmQWaquitDg&usg=AFQjCNF1bFXMtEcc_Ix-LrswfF_83caeCA
- 54 http://search.yahoo.co.jp/search?p=テンプレート 外部参照2&ei=UTF-8&fr=top_v2&x=wrt



