Reputation: 3
This is wholy mysterious to me. I'm using g++ on ubuntu, and this is some of my code (with class names change, but nothing else because I'm still using stubs everywhere):
Bob.hpp
template <class A>
class Bob : public Jack<Chris, A>
{
public:
Bob(int x1, int x2, float x3 = 1.0, float x4 = 2.0, float x5 = 3.0) throw(Exception);
virtual ~Bob();
};
I implemented in another file like this:
Bob.cpp
template <class A>
Bob<A>::Bob(int x1, int x2, float x3, float x4, float x5) throw(Exception)
{
}
template <class A>
Bob<A>::~Bob()
{
}
and I used it like this:
main.cpp
int main()
{
Bob<Alice> instance(1, 2);
}
Compiling with:
g++ -c Bob.cpp -o Bob.o
g++ -c main.cpp -o main.o
g++ -L"libs" -llib main.o Bob.o prog
gives me
main.o: In function main':
main.cpp:(.text+0x1fd): undefined reference to
Bob::Bob(int, int, float, float, float)'
collect2: ld returned 1 exit status
I am completely stumped. Changing the order with the g++ linking stage makes no difference. Compiling the object files generates no problems. And Why an undefined reference when I implemented the constructor? If anyone could shed any light on this, it's be much appreciated.
Upvotes: 0
Views: 214
Reputation: 99094
Where do you think the constructor of Bob<Alice>
should be defined? It wasn't defined in Bob.cpp, because there was no mention of a Bob<Alice>
in Bob.cpp. There was a template, which could have been used to define Bob<Alice>
when Bob.cpp was compiled into Bob.o, but it wasn't.
Put the template definition in Bob.hpp, or Bob<Alice>
in Bob.cpp.
Upvotes: 0
Reputation: 400
You need to move the code from Bob.cpp into Bob.hpp. When the compiler sees the definitions of Bob::Bob
and Bob::~Bob
in Bob.cpp, it does not know what types of Bob are actually going to be instantiated (i.e. Bob<int>
vs Bob<SomeClass>
and the code for them isn't generated.
Alternatively, you can still place the code in the Bob.cpp file, but you need to declare which types of Bob are going to be instantiated, e.g.:
Inside of Bob.cpp:
template
class Bob<Alice>;
Upvotes: 1
Reputation:
In addition to the issues raised by others, libraries must come last on the GCC command line. Instead of:
g++ -L"libs" -llib main.o Bob.o prog
you want:
g++ -L"libs" main.o Bob.o prog -llib
Upvotes: 0
Reputation: 99565
The declarations and definitions of the class template member functions should all be in the same header file.
When compiling Bob.cpp
, the compiler has both the declarations and the definitions available. At this point the compiler does not need to generate any definitions for template classes, since there are no instantiations. When the compiler compiles main.cpp
, there is an instantiation: template class Bob<Alice>
. At this point the compiler has the declarations but no definitions!
Upvotes: 1