In case you have a project where you use a templated class that is split in its own header (
.h) and source (
.cpp) files, if you compile the class, into an object file (
.o), separately from the code that uses it, you will get the
undefined reference to error at linking.
Lets assume we have
Stack.h which define a templated stack using vectors. And
main.cpp that uses this class after including
If you try to compile these files as mentioned above, one by one, later you will get a linking error saying
undefined reference to for the methods of the class.
The code in the template is not sufficient to instruct the compiler to produce the methods that are needed by
Stack<string>::push(...)) as the compiler does not know, while compiling
Stack.cpp by itself, the data types it should provide support for.
The reason it allows you to compile these incomplete objects is the following:
main.cpp: the compiler will implicitly instantiate the template classes
Stack<string>because those particular instantiations are requested in
main.cpp. Since the implementations of those member functions are not in
main.cpp, nor in any header file included in
Stack.h), the compiler will not include complete versions of those functions in
main.oand it will expect to find them in another object during linking.
Stack.cpp: the compiler won’t compile the instantiations of
Stack<string>neither as there are no implicit or explicit instantiations of them in
So in the end, neither of the
.o files contain the actual implementations of
Stack<string> and the linking fails.
Solution 1 : Explicitly instantiate the template
At the end of
Stack.cpp, you can explicitly instantiate all needed templates.
In our example we would add:
template class Stack<int>; template class Stack<std::string>;
This will ensure that, when the compiler is compiling
Stack.cpp that it will explicitly compile all the code needed for the
Using this method, you should ensure that all the of the implementation is placed into one
.cpp file and that the explicit instantation is placed after the definition of all the functions (for example, at the end of the file).
A problem with this method is that it forces you to update the
Stack.cpp file each time you want to add support for a new data type (or remove one).
Solution 2 : Move the implementation code into the header file
Move all the source code of
Stack.h, and then delete
Stack.cpp. Using this method you do not need to manually instantiate all possible data types that are needed and thus you do not need to modify code of the class. As a side-effect, if you use the header file in many other source files, it will compile the functions of the header file in each source. This can make compilation slower but it will not create any compilation/linking problems, as the linker will ignore the duplicate implementations.
Solution 3 : Move the implementation code into a new header file and include it in the original header file
Stack_impl.h, and then include
Stack.h to keep the implementation in a separate file from the declaration. This method will behave exactly like