Подтвердить что ты не робот

Почему реализация и объявление класса шаблона должны быть в одном заголовочном файле?

Почему реализация и объявление класса шаблона должны быть в одном заголовочном файле? Может ли кто-нибудь из вас объяснить это на примере?

4b9b3361

Ответ 1

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

Подробнее читайте Модель включения.

Ответ 2

Определение шаблона класса и реализация его функций-членов должно быть видимым для каждого места, которое создает экземпляр его с отдельным типом. т.е. для создания экземпляра myTemplate<int> вам необходимо увидеть полное определение и реализацию myTemplate.

Самый простой способ сделать это - поместить определение шаблона и его функций-членов в один заголовок, но есть и другие способы. Например, вы можете поместить реализацию функций-членов в отдельный файл, который был включен отдельно. Затем вы можете включить его из первого заголовка или включить только файл реализации, в котором он вам нужен.

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

то есть. если у вас есть myTemplate<int> и myTemplate<std::string>, определенные как extern, тогда вы можете использовать их в порядке, но если myTemplate<double> не определен extern, вы не сможете использовать это без реализации.

Ответ 3

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

В случае шаблонов компилятору также требуется определение для генерации кода.

Разница лучше объясняется в часто задаваемые вопросы по С++.

Ответ 4

Им не нужно.

Необходимо, чтобы определение шаблона было видимым в момент создания экземпляра (где оно использовалось), чтобы компилятор мог получить класс/функцию из шаблона в этой точке.

Однако чрезвычайно часто используется два файла заголовка для классов шаблонов:

// foo_fwd.hpp
template <typename T, typename U> struct Foo;

// foo.hpp
#include "foo_fwd.hpp"

template <typename T, typename U> struct Foo { typedef std::pair<T,U> type; };

Это позволяет тем, кому не требуется полное определение шаблона, включать несколько более легкий заголовок, например:

//is_foo.hpp
#include <boost/mpl/bool.hpp>
#include "foo_fwd.hpp"

template <typename Z>
struct is_foo: boost::mpl::false_ {};

template <typename T, typename U>
struct is_foo< Foo<T,U> >: boost::mpl::true_ {};

который может немного ускорить время компиляции.