Hatena::ブログ(Diary)

かせいさんとこ

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クラスについて

そんな感じー。

なおなお 2011/02/24 23:04 初めて知った
そういや先輩がそうしてた
あの時は怠慢な奴ぐらいに思ったが
そうじゃなかった

ちゃりちゃり 2011/05/26 19:27 助かりました。
こころから感謝いたします

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証