Давайте рассмотрим один пример, скажем, по какой-то причине вы хотите иметь шаблонный класс:
//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");
}
Без двух последних строк в заголовочном файле - 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.