Template Instantiation
I was looking around for something to wite a small article about
and this seems to a good one.
The forum gets a fair number of post concerning this problem where the OP has split
the template into a *.h file and a *.cpp file and gets linker
problems.
The usual answer given to this is to put all the template stuff into the *.h file
because it has to be done this way.
the class/functions.
That is not entirely true.
C++ has Implicit template instantiation and Explicit instantiation
IMPLICIT INSTANTIATION
In
template.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
|
#ifndef TEMPLATE_H
#define TEMPLATE_H
#include <iostream>
template <typename T>
class myTemplate
{
private:
T data;
public:
myTemplate();
myTemplate(T t);
T getData() const;
void displayData() const;
static int someValue;
};
template<typename T>
myTemplate<T>::myTemplate()
:data()
{
}
template<typename T>
myTemplate<T>::myTemplate(T t)
:data(t)
{
}
template <typename T>
T myTemplate<T>::getData() const
{
return data;
}
template <typename T>
void myTemplate<T>::displayData() const
{
std::cout << data <<std::endl;
}
template<typename T>
int myTemplate<T>::someValue = 100;
#endif
| |
In main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
#include <iostream>
#include "template.h"
using namespace std;
int main()
{
myTemplate<int> myTi(5);
myTi.displayData();
myTemplate<float> myTf(3.5f);
myTf.displayData();
return 0;
}
| |
In the example above, the complete template definition is in the header file
which is included by main.cpp - so there are no problems during compiling
and linking.
If we were to forget to do a definition of the
displayData() function
then we would have got a LINKER error NOT a COMPILER error.
//=========================================================================================//
EXPLICIT INSTANTIATION
Let's say we want to split our template class between a header file and a source file.
So we have main.cpp and template.cpp.
We compile both files but get Linker errors because NO actual code from the template.cpp
file would have been instantiated.
To get the compiler to instantiate the required code we can use explict instantiation.
template.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
#ifndef TEMPLATE_H
#define TEMPLATE_H
#include <iostream>
template <typename T>
class myTemplate
{
private:
T data;
public:
myTemplate();
myTemplate(T t);
T getData() const;
void displayData() const;
static int someValue;
};
#endif
| |
template.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
#include "template.h"
#include <iostream>
//template functions
template<typename T>
myTemplate<T>::myTemplate()
:data()
{
}
template<typename T>
myTemplate<T>::myTemplate(T t)
:data(t)
{
}
template <typename T>
T myTemplate<T>::getData() const
{
return data;
}
template <typename T>
void myTemplate<T>::displayData() const
{
std::cout << data <<std::endl;
}
template<typename T>
int myTemplate<T>::someValue = 100;
//The explicit instantiation part
template class myTemplate<int>;
template class myTemplate<float>;
| |
main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
#include <iostream>
#include "template.h"
using namespace std;
int main()
{
myTemplate<int> myTi(5);
myTi.displayData();
myTemplate<float> myTf(3.5f);
myTf.displayData();
return 0;
}
| |
The important part is the last couple of lines in
template.cpp
We know that we will be needing a
myTemplate<int> and a
myTemplate<float>
so we explicitly ask the compiler to generate code for all the instantiable parts for these
two class types.
Notice the way the instantiation directive is written.
We can now compile and link our code successfully.
We can also explicitly instantiate template functions, or individual template class member functions.