О шаблоне C ++ и явном объявлении - PullRequest
1 голос
/ 21 августа 2011

Я потратил около 20 минут, пытаясь выяснить, почему некоторые мои методы шаблона прошли компиляцию, но не связывание.

Оказывается, мне нужно было явно объявить мой метод шаблона.

Этобыло что-то в этом роде:

class Test {
   template<class Source> void Save(Source& obj);
};

Тогда я бы использовал это где-то так:

Test t;
ClassDerivedFromInterface obj;
t.Save(obj);

Это скомпилировалось нормально, но не связывалось.Пока я не добавил:

template void Test::Save(ClassDerivedFromInterface);

Я хотел бы понять, в каком случае необходимо явное объявление.

Спасибо

Ответы [ 4 ]

5 голосов
/ 21 августа 2011

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

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

Следовательно,Фактически скомпилированный код для вашей функции Save(ClassDerivedFromInterface&) не появится, пока вы не напишите эту строку.Если видно только объявление шаблона функции, то шаблон создает объявление только конкретной функции, но не ее тела, и поэтому во время ссылки вы заметите, что функция отсутствует.

Напомним,Сами шаблоны не могут быть скомпилированы, это могут быть только их конкретные экземпляры, и вы должны обратить внимание на то, чтобы конкретные экземпляры всегда были доступны при их создании.Явное создание экземпляра в том виде, в котором оно есть, работает и позволяет вам упаковать несколько конкретных экземпляров в отдельный TU, но, как правило, это сложно поддерживать и не масштабируемо, и существуют другие недостатки явного создания экземпляров, которых вы избегаете, когда вы позволяете компилятору создавать неявно.Поэтому обычно лучше упаковать все ваши определения в заголовочный файл.

2 голосов
/ 21 августа 2011

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

template.h - template declarations
template.cpp - template definitions
main.cpp - template usage

template.cpp не входит в main.cpp и поэтому недоступен для пользователя шаблона, поэтому вам нужны явные объявления.
Но если ваша структура:

template.h - template declarations and definitions
main.cpp - template usage

объявления шаблона доступны пользователю шаблона, поэтому вам не нужны явные объявления.

2 голосов
/ 21 августа 2011

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

C ++ FAQ 35.13

1 голос
/ 21 августа 2011

Компилятор должен знать, какие типы вы собираетесь использовать с вашим шаблоном. Если вы создаете шаблонный класс и затем используете его, например, с int, char и double, то компилятор создаст методы для шаблона для этих типов. Если вы скомпилируете метод шаблона в отдельном модуле компиляции, из которого вы его используете, компилятор не будет создавать экземпляр вашего шаблона для нужного вам типа. Но если вы явно создадите экземпляр шаблона, компилятор создаст все, что вы ему скажете.

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