Question

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 toBob::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.

Was it helpful?

Solution

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>;

OTHER TIPS

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!

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

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top