Undefined reference to template class constructor
This is a common question in C++ programming. There are two valid answers to this. There are advantages and disadvantages to both answers and your choice will depend on context. The common answer is to put all the implementation in the header file, but there's another approach will will be suitable in some cases. The choice is yours.
The code in a template is merely a 'pattern' known to the compiler. The compiler won't compile the constructors cola<float>::cola(...)
and cola<string>::cola(...)
until it is forced to do so. And we must ensure that this compilation happens for the constructors at least once in the entire compilation process, or we will get the 'undefined reference' error. (This applies to the other methods of cola<T>
also.)
Understanding the problem
The problem is caused by the fact that main.cpp
and cola.cpp
will be compiled separately first. In main.cpp
, the compiler will implicitly instantiate the template classes cola<float>
and cola<string>
because those particular instantiations are used in main.cpp
. The bad news is that the implementations of those member functions are not in main.cpp
, nor in any header file included in main.cpp
, and therefore the compiler can't include complete versions of those functions in main.o
. When compiling cola.cpp
, the compiler won't compile those instantiations either, because there are no implicit or explicit instantiations of cola<float>
or cola<string>
. Remember, when compiling cola.cpp
, the compiler has no clue which instantiations will be needed; and we can't expect it to compile for every type in order to ensure this problem never happens! (cola<int>
, cola<char>
, cola<ostream>
, cola< cola<int> >
... and so on ...)
The two answers are:
- Tell the compiler, at the end of
cola.cpp
, which particular template classes will be required, forcing it to compilecola<float>
andcola<string>
. - Put the implementation of the member functions in a header file that will be included every time any other 'translation unit' (such as
main.cpp
) uses the template class.
Answer 1: Explicitly instantiate the template, and its member definitions
At the end of cola.cpp
, you should add lines explicitly instantiating all the relevant templates, such as
template class cola<float>;
template class cola<string>;
and you add the following two lines at the end of nodo_colaypila.cpp
:
template class nodo_colaypila<float>;
template class nodo_colaypila<std :: string>;
This will ensure that, when the compiler is compiling cola.cpp
that it will explicitly compile all the code for the cola<float>
and cola<string>
classes. Similarly, nodo_colaypila.cpp
contains the implementations of the nodo_colaypila<...>
classes.
In this approach, you should ensure that all the of the implementation is placed into one .cpp
file (i.e. one translation unit) and that the explicit instantation is placed after the definition of all the functions (i.e. at the end of the file).
Answer 2: Copy the code into the relevant header file
The common answer is to move all the code from the implementation files cola.cpp
and nodo_colaypila.cpp
into cola.h
and nodo_colaypila.h
. In the long run, this is more flexible as it means you can use extra instantiations (e.g. cola<char>
) without any more work. But it could mean the same functions are compiled many times, once in each translation unit. This is not a big problem, as the linker will correctly ignore the duplicate implementations. But it might slow down the compilation a little.
Summary
The default answer, used by the STL for example and in most of the code that any of us will write, is to put all the implementations in the header files. But in a more private project, you will have more knowledge and control of which particular template classes will be instantiated. In fact, this 'bug' might be seen as a feature, as it stops users of your code from accidentally using instantiations you have not tested for or planned for ("I know this works for cola<float>
and cola<string>
, if you want to use something else, tell me first and will can verify it works before enabling it.").
Finally, there are three other minor typos in the code in your question:
- You are missing an
#endif
at the end of nodo_colaypila.h - in cola.h
nodo_colaypila<T>* ult, pri;
should benodo_colaypila<T> *ult, *pri;
- both are pointers. - nodo_colaypila.cpp: The default parameter should be in the header file
nodo_colaypila.h
, not in this implementation file.
C++ undefined reference to template class method
Typically you want your template methods in the header, so they are compiled when needed. In case you really want to hide it in the implementation file, you have to explicitly instantiate the template in Graph.cpp
like
template class Graph<string>;
Since you have to do that for every type T
you intend to use with Graph<T>
, the point of the template class is somewhat defeated and you better put everything into the header
Undefined reference when using template
You receive this error because compiler did not generate the code for this template type. One of solutions is to tell the compiler to do this explicitly by template instantiation:
add to your DenseTrafficHandler.cpp:
template class DenseTrafficHandler<unsigned short>;
Yes, just implement it in the header file. Reading more about it here.
C++ undefined reference to template method
Template classes/functions must be defined in the header file, not in .cpp
see: Why can templates only be implemented in the header file?
undefined reference to template function
The implementation of a non-specialized template must be visible to a translation unit that uses it.
The compiler must be able to see the implementation in order to generate code for all specializations in your code.
This can be achieved in two ways:
1) Move the implementation inside the header.
2) If you want to keep it separate, move it into a different header which you include in your original header:
util.h
namespace Util
{
template<class T>
QString convert2QString(T type , int digits=0);
}
#include "util_impl.h"
util_impl.h
namespace Util
{
template<class T>
QString convert2QString(T type, int digits=0)
{
using std::string;
string temp = (boost::format("%1") % type).str();
return QString::fromStdString(temp);
}
}
C++ template, linking stage undefined reference error
Make your class abstract (by adding = 0
), something like:
template <class T, class R>
class Gathering {
public:
virtual R gather(const T&) = 0;
};
C++ templates, undefined reference
You need to use the export
keyword. However, I don't think G++ has proper support, so you need to include the template function's definition in the header so the translation unit can use it. This is because the <int>
'version' of the template hasn't been created, only the <typename T>
'version.'
An easy way is to #include
the .cpp file. However, this can cause problems, e.g. when other functions are in the .cpp file. It will also likely increase the compile time.
A clean way is to move your template functions into its own .cpp file, and include that in the header or use the export
keyword and compile it separately.
More information on why you should try and put template function definitions in its header file (and ignore export
altogether).
Undefined reference error for template method
Templated code implementation should never be in a .cpp
file: your compiler has to see them at the same time as it sees the code that calls them (unless you use explicit instantiation to generate the templated object code, but even then .cpp
is the wrong file type to use).
What you need to do is move the implementation to either the header file, or to a file such as VAConfig.t.hpp
, and then #include "VAConfig.t.hpp"
whenever you use any templated member functions.
Error message undefined reference to template function passed as template parameter
It seems the problem is a gcc error: the code compiles and links with clang, icc, and the EDG frontend. A potential work-around not changing any of the uses would be the use of a class template identity
instead of a function:
template<int I>
struct identity {
operator int() { return I; }
};
template<typename fn>
class Base {
public:
int f() {
return fn();
}
};
Related Topics
Unsequenced Value Computations (A.K.A Sequence Points)
Why How to Not Brace Initialize a Struct Derived from Another Struct
How to Sort the Texture Positions Based on the Texture Indices Given in a Wavefront (.Obj) File
What Does Flushing the Buffer Mean
How to Get the Class Name from a C++ Object
What Is Copy Elision and How Does It Optimize the Copy-And-Swap Idiom
How to Create a New Operator in C++ and How
Why Does -Int_Min = Int_Min in a Signed, Two's Complement Representation
How to Create an Array When the Size Is a Variable Not a Constant
Forward Declare a Standard Container
Why Can't I Write to a String Literal While I *Can* Write to a String Object
How to Properly Use Std::String on Utf-8 in C++
How Does the Standard Library Implement Std::Swap
How to Create a Pause/Wait Function Using Qt
Why Don't Stl Containers Have Virtual Destructors
Why Cannot a Non-Member Function Be Used for Overloading the Assignment Operator