Кратко
Определение и свойства
Проблема разделения шаблона
При использовании шаблонов в C++ требуется, чтобы определения всех шаблонных функций находились в том же заголовочном файле, что и их объявления. Это обусловлено тем, что компилятор должен видеть определения шаблонных функций при инстанцировании шаблонов с конкретными типами.
Причины проблемы
- Инстанцирование шаблонов: Компилятор должен видеть полный код шаблонной функции, чтобы создать специализированный код для конкретных типов.
- Отсутствие разделения компиляции: В отличие от обычных функций, шаблонные функции не могут быть скомпилированы отдельно, так как компилятор не знает, с какими типами они будут использоваться.
Пример
Пример шаблона класса
// Заголовочный файл: MyTemplate.h
#ifndef MYTEMPLATE_H
#define MYTEMPLATE_H
template<typename T>
class MyTemplate {
public:
MyTemplate(T value);
void display() const;
private:
T value;
};
// Определение должно быть в заголовочном файле
template<typename T>
MyTemplate<T>::MyTemplate(T value) : value(value) {}
template<typename T>
void MyTemplate<T>::display() const {
std::cout << value << std::endl;
}
#endif // MYTEMPLATE_H
Пример использования шаблона
// Основной файл: main.cpp
#include <iostream>
#include "MyTemplate.h"
int main() {
MyTemplate<int> intObj(10);
intObj.display();
MyTemplate<std::string> stringObj("Hello");
stringObj.display();
return 0;
}
Решение проблемы
Решение 1: Полное определение в заголовочном файле
Разместить все определения шаблонных функций в заголовочном файле, как показано в примере выше.
Решение 2: Включение файла с определением
Можно разделить объявление и определение, но включать файл с определением в конце заголовочного файла.
// Заголовочный файл: MyTemplate.h
#ifndef MYTEMPLATE_H
#define MYTEMPLATE_H
template<typename T>
class MyTemplate {
public:
MyTemplate(T value);
void display() const;
private:
T value;
};
#include "MyTemplate.tpp" // Включение файла с определениями
#endif // MYTEMPLATE_H
// Файл с определениями: MyTemplate.tpp
template<typename T>
MyTemplate<T>::MyTemplate(T value) : value(value) {}
template<typename T>
void MyTemplate<T>::display() const {
std::cout << value << std::endl;
}