These are my files:
--------[ 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
I'm able to generate ".o" files for all the above files, with the command g++ -c main.cpp and g++ -c c.cpp and so on. But when I try linking the ".o" files with g++ -o car c.o main.o v.o I get this error:
main.o: In function `main':
main.cpp:(.text+0x17): undefined reference to `void C::call<Merc>(Merc&)'
collect2: ld returned 1 exit status
The error goes away when I uncomment the line #include "c.cpp" in main.cpp, but I feel it may be bad practice to include the cpp file this way. Am I doing this wrong? Is there a better way to cater to templated declarations while creating separate object files and linking them? p.s: I'm using the templated function in a much more complex class structure. What is shown here is just a small example for the sake of showing you the kind of error I'm facing.
A way to solve this problem is to
a. remove '#include "c.hpp"' from c.cpp AND
b. include 'c.cpp' at the end of 'c.hpp' (strange sounding '#include "c.pp"')
This way the template definitions are availabe to each translation unit that includes 'c.hpp' without explicitly doing so in each .cpp file. This is called the 'inclusion model'
I believe this is because when you compile c.cpp
the compiler doesn't know it needs to generate code for C::call<Merc>(Merc&)
, and when you're compiling main.cpp
it doesn't have the definition of C::call<T>(T&)
from which to instantiate C::call<Merc>(Merc&)
.
Template definitions are essentially semantic macros, so much like the preprocessor's #define
lexical macros they must be visible in the compilation units that use them.
Essentially, you cannot have related template declarations and definitions in separate files in current C++. You should fully define class C in one file.
来源:https://stackoverflow.com/questions/3878884/templated-function-being-reported-as-undefined-reference-during-compilation