Weźmy jeden przykład, powiedzmy z jakiegoś powodu, że chcesz mieć klasę szablonów:
//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");
}
Jeśli skompilujesz ten kod za pomocą Visual Studio - działa on od razu po rozpakowaniu. gcc wyświetli błąd linkera (jeśli ten sam plik nagłówkowy jest używany z wielu plików .cpp):
error : multiple definition of `DemoT<int>::test()'; your.o: .../test_template.h:16: first defined here
Możliwe jest przeniesienie implementacji do pliku .cpp, ale wtedy musisz zadeklarować klasę w ten sposób -
//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>;
A potem .cpp będzie wyglądać tak:
//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");
}
Bez dwóch ostatnich wierszy w pliku nagłówkowym - gcc będzie działało dobrze, ale Visual Studio wyświetli błąd:
error LNK2019: unresolved external symbol "public: void __cdecl DemoT<int>::test(void)" (?test@?$DemoT@H@@QEAAXXZ) referenced in function
składnia klasy szablonów jest opcjonalna, jeśli chcesz udostępnić funkcję poprzez eksport .dll, ale dotyczy to tylko platformy Windows - test_template.h mógłby wyglądać następująco:
//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();
z plikiem .cpp z poprzedniego przykładu.
To jednak powoduje więcej bólu głowy dla linkera, więc zaleca się użycie poprzedniego przykładu, jeśli nie eksportujesz funkcji .dll.