Файл шаблона (.tpp) включает охрану - PullRequest
0 голосов
/ 25 января 2019

При написании шаблонных классов я хотел бы переместить реализацию в другой файл (myclass.tpp) и включить его в конец основного заголовка (myclass.hpp).

Мой вопрос: сделатьМне нужно включить охрану в файл .tpp или достаточно, чтобы они были в файле .hpp?

Пример кода:

myclass.hpp

#ifndef MYCLASS_HPP
#define MYCLASS_HPP

template<typename T>
class MyClass
{
public:
    T foo(T obj);
};

//include template implemetation
#include "myclass.tpp"

#endif

myclass.tpp

#ifndef MYCLASS_TPP //needed?
#define MYCLASS_TPP //needed?

template<typename T>
T MyClass<T>::foo(T obj)
{
    return obj;
}

#endif //needed?

Ответы [ 2 ]

0 голосов
/ 25 января 2019

Просто используйте pragma once во всех файлах заголовков.Компилятор обеспечит включение вашего файла только один раз.Компилятор может не распознать только в очень необоснованном состоянии: кто-то структурирует свои каталоги включения, используя жесткую ссылку.Кто это делает?Если кто-то не может найти уникальное имя для своего файла, почему он должен быть более опытным, чтобы найти уникальное имя для каждого включаемого охранника для всех заголовочных файлов?

С другой стороны, включаемый охранник может быть поврежден, потому чтоимя макроса не будет таким уникальным из-за копирования / вставки или заголовочного файла, созданного путем первого копирования другого и т. д. *

Как выбирается уникальное имя макроса : <project name>_<filename>?Как это может быть более уникальным, чем уникальность, основанная на всей структуре корневого каталога?

Итак, в конце концов, при выборе между include guard или pragma once следует учитывать стоимость работы, которая необходима дляобеспечить уникальность:

1 - для pragma once вам нужно только убедиться, что структура вашей системы не перепутана благодаря жестким ссылкам.

2 - для includeСтраж для каждого файла в вашей системе, вы должны убедиться, что имя макроса является уникальным.

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

0 голосов
/ 25 января 2019

Нужно ли включать охранники в файл .tpp или достаточно, чтобы они были в файле .hpp?

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

  • Ужасно полезно : они позволяют объявлять зависимость от нескольких файлов, не отслеживая, какие файлы уже были включены.
  • Дешевый : это всего лишь некоторые токены перед компиляцией.
  • Неразрывный : они хорошо подходят для большинства случаев использования #include(У меня был коллега, который не знал, как писать макросы, поэтому он #include d файлы реализации * facepalm *).
  • Ожидается : разработчикизнать, что они есть, и едва замечать их;напротив, отсутствует заголовочный файл, включающий охранников, который будит нас и добавляет к глобальному счетчику wtf / line.

Я пользуюсь возможностью, чтобы выделить комментарий от StoryTeller:

Я бы пошел дальше и добавил описательную директиву #error, если защита hpp не определена.Просто чтобы предложить небольшую защиту от людей, включая tpp.

Что будет означать:

#ifndef MYCLASS_TPP
#define MYCLASS_TPP

#ifndef MYCLASS_HPP
#error __FILE__ should only be included from myclass.hpp.
#endif // MYCLASS_HPP

template<typename T>
T MyClass<T>::foo(T obj)
{
    return obj;
}

#endif // MYCLASS_TPP

Обратите внимание: если сначала переводится единица #include <myclass.hpp>, а затем #include <myclass.tpp> ошибка не выдается и все в порядке.

...