Vamos dar um exemplo, digamos que, por algum motivo, você queira ter uma classe de modelo:
//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");
}
Se você compilar esse código com o Visual Studio, ele funcionará imediatamente. O gcc produzirá um erro de vinculador (se o mesmo arquivo de cabeçalho for usado em vários arquivos .cpp):
error : multiple definition of `DemoT<int>::test()'; your.o: .../test_template.h:16: first defined here
É possível mover a implementação para o arquivo .cpp, mas você precisa declarar uma classe como esta -
//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>;
E então o .cpp ficará assim:
//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");
}
Sem duas últimas linhas no arquivo de cabeçalho - o gcc funcionará bem, mas o Visual studio produzirá um erro:
error LNK2019: unresolved external symbol "public: void __cdecl DemoT<int>::test(void)" (?test@?$DemoT@H@@QEAAXXZ) referenced in function
A sintaxe da classe de modelo é opcional, caso você queira expor a função via exportação .dll, mas isso é aplicável apenas à plataforma Windows - para que test_template.h possa se parecer com o seguinte:
//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();
com o arquivo .cpp do exemplo anterior.
No entanto, isso dá mais dor de cabeça ao vinculador, por isso é recomendável usar o exemplo anterior se você não exportar a função .dll.