Шаблоны C ++ объявляются в .h, определяются в .hpp - PullRequest
18 голосов
/ 20 августа 2010

Я видел некоторый код, в котором разработчик определил шаблон класса в файле .h и определил его методы в файле .hpp. Это застало меня врасплох.

Существуют ли особые соглашения в C ++ при работе с шаблонами и в каких файлах они должны быть?

Например, скажем, у меня был шаблон класса Vector с методами для векторных операций (сложение, вычитание, точка и т. Д.). Я также хотел бы специализировать определенные функции, если аргумент шаблона равен float (операторы сравнения). Как бы вы все это разделили между файлами (укажите, есть ли .h, .hpp, .cpp).

Ответы [ 7 ]

18 голосов
/ 20 августа 2010

Обычно (по моему опыту, YMMV) файл hpp представляет собой #include файл CPP. Это сделано для того, чтобы разбить код на два физических файла: первичное включение и файл сведений о реализации, о которых пользователям вашей библиотеки не нужно знать. Это делается так:

super_lib.h (единственный файл, который нужен вашим клиентам #include)

template<...> class MyGizmo
{
public:
  void my_fancy_function();
};

#include "super_lib_implementation.hpp"

super_lib_implementation.hpp (ваши клиенты не #include это напрямую)

template<...> void MyGizmo<...>::my_fancy_function()
{
 // magic happens
}
2 голосов
/ 20 августа 2010

Мне кажется, что это неправильный способ разделения кода..h означает заголовок и .hpp для C ++ заголовок обычно.Помещение определений шаблонов в .hpp, в то время как другой код в .h, кажется, злоупотребляет расширением файла.

Код шаблона обычно все пишется в одном заголовке вместе с объявлением шаблона или в другом заголовке, который также может быть специально добавлен с суффиксом, таким как .tcc или что-то еще, и затем включается в заголовок, в который помещаются объявления шаблонаНо на самом деле, расширение файла не имеет значения, если вы последовательны в своем проекте.

Исключения составляют случаи, когда вы используете явные экземпляры и точно знаете, какие именно экземпляры вам понадобятся.Представьте, что у вас есть шаблон и два его экземпляра:

template<typename T>
struct SymbolTable {
  T *lookup();
  // ...
};

template struct SymbolTable<GlobalSym>;
template struct SymbolTable<LocalSym>;

Вам не нужно помещать определение lookup и другие в заголовок.Вы можете поместить их все в файл .cpp вместе с двумя явными директивами создания экземпляров.

Последний вопрос, о котором вы спрашиваете, касается другой темы: явные специализации.Я рекомендую вам сделать отдельный вопрос об этом.В двух словах, явные определения специализации, где все аргументы шаблона имеют конкретные значения / типы, должны быть помещены в файл .cpp, но их объявления необходимо поместить в заголовок (чтобы сообщить другим, что эти определенные члены являются специализированными).

2 голосов
/ 20 августа 2010

Это звучит необычно для меня. Определение шаблона и все специализации должны быть скомпилированы вместе с его объявлением, за исключением шаблонов export, которых практически не существует.

C ++ 0x вводит extern объявления шаблонов, которые позволяют вам определять явные специализации в другом исходном файле (единица перевода). Это уже существует как расширение в GCC и, возможно, на других платформах.

Разделение на два файла может помочь немного "спрятать" реализацию или позволить некоторую лень с doxygen, может быть.

Aha! Также возможно улучшить время компиляции с предварительно скомпилированными заголовками. Компилятор может кэшировать заголовки отдельно для каждого файла. Затем можно изменить отдельный заголовок «реализация», не касаясь заголовка «interface». Но не наоборот, заголовок реализации по-прежнему занимал бы большую часть времени компиляции, а выигрыш был бы очень хрупким и зависел от платформы и конкретных внесенных изменений. В конце концов, PCH сокращает время работы с несколькими исходными файлами, а оптимизация зависимостей заголовка не имеет смысла.

1 голос
/ 20 августа 2010

Я думаю, что одним из аспектов разделения файла интерфейса (.h) и файла реализации (.hpp) является то, что пользователю шаблона (то есть другому разработчику) нужно только взглянуть на файл .h, чтобы понять, как использоватьшаблон, не отвлекаясь на его фактическую реализацию.

1 голос
/ 20 августа 2010

Я никогда не слышал о том, чтобы помещать объявления классов в .h и определения шаблонов в .hpp. Каждый проект, который я видел, использовал подход, который .h и .hpp означал одно и то же, и вы должны стандартизировать один (обычно .h).

Методы шаблона могут быть помещены в конец файла .h или в отдельные файлы -inl.h (например, Руководство по стилю Google C ++ ).

0 голосов
/ 17 августа 2015

Библиотека Boost использует «.hpp» для заголовков, содержащих объявление и реализацию. В таких случаях нет необходимости связываться с (предварительно скомпилированной) библиотекой.

Что касается идеи Boost, такое расширение, как ".inl", может быть хорошей идеей для описания исходного файла "реализации" заголовка объявления шаблона.

0 голосов
/ 20 августа 2010

Если мы определим шаблон класса в файле .h и определим его методы в файле .hpp , тогда мы должны #include файл .hpp в файле .h. Проще определить методы в конце файла .h (тогда файл .hpp не требуется).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...