Можно ли и нужно ли выносить определение метода шаблонного класса в .cpp файл?

Рейтинг: 0Ответов: 1Опубликовано: 25.05.2023

У меня есть шаблонный класс и его конструктор. Для обычных классов я пишу объявления в .hpp файле и определения к ним в .cpp файле. На сколько правильным будет делать такой вынос определения в .cpp файл в случае с конструктором шаблонного классам или другими его методами? Я пробовал реализовывать это примерно так (вроде бы работает, но громоздко):

// .hpp
...ъх
template<typename type>
class NAME
{
  public:
    NAME(type arg);
};

// .cpp
...
template<typename type>
NAME<type>::NAME(type arg)
{
// определение
}

На некоторых форумах люди говорят, что правильнее оставлять определение в заголовочном классе. Но как по мне, это будет сильно ломать всю структуру проекта. Или не будет?

Спасибо!

Ответы

▲ 0Принят

Пока шаблон не инстанцирован - класса не существует, поэтому он должен быть в хэдере. Вы его просто не сможете создать в сорсах. Точнее, вы его не сможете в этом случае объявлять в других файлах, т.е. разделяемый шаблон обязательно должен быть в хэдере.

Вы можете выносить определение метода шаблона класса за скобки, но от этого метод не перестаёт быть частью этого шаблона.

В сорсах может быть только явное или неявное инстанцирование шаблона:

#include <vector>

// explicit template instantiation
template class std::vector<short>; 

// Не путать со специализацией
// full template specialization
// template<> class MyVector<short> { ... };

int main() {
    // implicit template instantiation
    std::vector<int> vector;
    return 0;
}

На самом деле, начиная с C++17 ключевое слово inline по сути стало указанием компилятору, что объект должен быть объявлен один раз (ODR). И вы можете выносить определения методов за скобки просто добавив спецификатор inline (не имеет смысла для шаблона), написав таким образом header-only библиотеку.

Иными словами, определение методов класса вовсе не обязательно выводить в файл сорсов даже если класс не шаблонный, а для шаблона класса так делать вообще нельзя.