一例を挙げましょう。何らかの理由でテンプレートクラスが必要だとします。
//test_template.h:
#pragma once
#include <cstdio>
template <class T>
class DemoT
{
public:
void test()
{
printf("ok\n");
}
};
template <>
void DemoT<int>::test()
{
printf("int test (int)\n");
}
template <>
void DemoT<bool>::test()
{
printf("int test (bool)\n");
}
このコードをVisual Studioでコンパイルする場合-そのまま使用できます。gccはリンカーエラーを生成します(複数の.cppファイルから同じヘッダーファイルが使用されている場合):
error : multiple definition of `DemoT<int>::test()'; your.o: .../test_template.h:16: first defined here
実装を.cppファイルに移動することは可能ですが、その場合は次のようにクラスを宣言する必要があります-
//test_template.h:
#pragma once
#include <cstdio>
template <class T>
class DemoT
{
public:
void test()
{
printf("ok\n");
}
};
template <>
void DemoT<int>::test();
template <>
void DemoT<bool>::test();
// Instantiate parametrized template classes, implementation resides on .cpp side.
template class DemoT<bool>;
template class DemoT<int>;
そして、.cppは次のようになります。
//test_template.cpp:
#include "test_template.h"
template <>
void DemoT<int>::test()
{
printf("int test (int)\n");
}
template <>
void DemoT<bool>::test()
{
printf("int test (bool)\n");
}
ヘッダーファイルに最後の2行がない場合、gccは正常に動作しますが、Visual Studioはエラーを生成します。
error LNK2019: unresolved external symbol "public: void __cdecl DemoT<int>::test(void)" (?test@?$DemoT@H@@QEAAXXZ) referenced in function
.dllエクスポートを介して関数を公開する場合、テンプレートクラスの構文はオプションですが、これはWindowsプラットフォームにのみ適用できるため、test_template.hは次のようになります。
//test_template.h:
#pragma once
#include <cstdio>
template <class T>
class DemoT
{
public:
void test()
{
printf("ok\n");
}
};
#ifdef _WIN32
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT
#endif
template <>
void DLL_EXPORT DemoT<int>::test();
template <>
void DLL_EXPORT DemoT<bool>::test();
前の例の.cppファイルを使用します。
ただし、これによりリンカーの頭痛が増えるため、.dll関数をエクスポートしない場合は前の例を使用することをお勧めします。