Кратко

Определение и свойства

Проблема разделения шаблона

При использовании шаблонов в 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;
}