Шаблонная функция сообщается как «неопределенная ссылка» во время компиляции - PullRequest
0 голосов
/ 07 октября 2010

Это мои файлы:

-------- [c.hpp] --------

#ifndef _C
#define _C

#include<iostream>
class C
{
public:
    template<class CARTYPE> void call(CARTYPE& c);
};

#endif

-------- [c.cpp] --------

#include "c.hpp"

template<class CARTYPE> void C::call(CARTYPE& c)
{
    //make use of c somewhere here
    std::cout<<"Car"<<std::endl;
}

-------- [v.cpp] --------

class Merc
{};

-------- [main.cpp] --------

#include "c.hpp"
#include "v.cpp"
//#include "c.cpp"

int main()
{
    Merc m; 
    C someCar;
    someCar.call(m);

}//main

Я могу сгенерировать файлы ".o" для всех вышеперечисленных файлов с помощью команды g ++ -c main.cpp и g ++ -c c.cpp и так далее. Но когда я пытаюсь связать файлы ".o" с g ++ -o car c.o main.o v.o Я получаю эту ошибку:

main.o: In function `main':
main.cpp:(.text+0x17): undefined reference to `void C::call<Merc>(Merc&)'
collect2: ld returned 1 exit status

Ошибка исчезает, когда я раскомментирую строку #include "c.cpp" в main.cpp, но я считаю, что включать файл cpp таким способом может быть плохой практикой. Я делаю это неправильно? Есть ли лучший способ обслуживать шаблонные объявления при создании отдельных объектных файлов и их связывании? PS: я использую шаблонную функцию в гораздо более сложной структуре классов. То, что показано здесь, является лишь небольшим примером, чтобы показать вам тип ошибки, с которой я сталкиваюсь.

Ответы [ 3 ]

2 голосов
/ 07 октября 2010

Я считаю, что это потому, что когда вы компилируете c.cpp, компилятор не знает, что ему нужно генерировать код для C::call<Merc>(Merc&), а когда вы компилируете main.cpp, он не имеет определения C::call<T>(T&)из которого можно создать экземпляр C::call<Merc>(Merc&).

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

1 голос
/ 07 октября 2010

Способ решения этой проблемы -

а. удалить '#include "c.hpp" из c.cpp AND

б. включите 'c.cpp' в конце 'c.hpp' (странное звучание '#include "c.pp"')

Таким образом, определения шаблонов доступны для каждой единицы перевода, которая включает в себя «c.hpp», без явного указания в каждом файле .cpp. Это называется 'модель включения'

0 голосов
/ 07 октября 2010

По сути, вы не можете иметь связанные объявления и определения шаблона в отдельных файлах в текущем C ++. Вы должны полностью определить класс C. в одном файле.

...