Шаблоны C ++, неопределенная ссылка - PullRequest
28 голосов
/ 16 марта 2009

У меня есть функция, объявленная так:

template <typename T> 
T read();

и определено так:

template <typename T>
T packetreader::read() {
    offset += sizeof(T);
    return *(T*)(buf+offset-sizeof(T)); 
}

Однако, когда я пытаюсь использовать его в своей функции main ():

packetreader reader;
reader.read<int>();

Я получаю следующую ошибку от g ++:

g++ -o main main.o packet.o
main.o: In function `main':
main.cpp:(.text+0xcc): undefined reference to `int packetreader::read<int>()'
collect2: ld returned 1 exit status
make: *** [main] Error 1

Кто-нибудь может указать мне правильное направление?

Ответы [ 4 ]

24 голосов
/ 16 марта 2009

Вам необходимо использовать ключевое слово export. Однако я не думаю, что G ++ имеет надлежащую поддержку, поэтому вам нужно включить определение функции шаблона в заголовок, чтобы модуль перевода мог использовать ее. Это связано с тем, что <int> 'версия' шаблона не была создана, только <typename T> 'версия.'

Простой способ - #include .cpp файл. Однако это может вызвать проблемы, например, когда другие функции находятся в файле .cpp. Это также, вероятно, увеличит время компиляции.

Чистый способ - переместить функции шаблона в собственный файл .cpp и включить его в заголовок или , использовать ключевое слово export и скомпилировать его отдельно.

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

12 голосов
/ 16 марта 2009

Проблема в том, что шаблон функции не является функцией. Это шаблон для создания необходимых функций.

Таким образом, для работы шаблона компилятору интуитивно нужны две части информации: сам шаблон и тип, который следует подставить в него. Это не похоже на вызов функции, который компилятор может сгенерировать, как только узнает, что функция существует. Ему не нужно знать, что делает функция, просто она выглядит как void Frobnicate(int, float) или какова ее подпись.

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

4 голосов
/ 16 марта 2009

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

Когда export для шаблонов будет больше поддерживаться, это не будет иметь место, но сейчас его вряд ли можно использовать.

0 голосов
/ 16 марта 2009

Является ли какой-либо шаблон поддержки их компилятором отдельной компиляцией?

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

...