The common procedure in C++ is to put class definition in a C++ header file and the implementation in a C++ source file. Then the source file is made part of the project, meaning compiled separately. But when we implement this procedure for template class, some compilation and linking problem will arise.
1. Compilation
PROBLEM
Sample Code:
Template Class Header File
// TestTemp.h
#ifndef _TESTTEMP_H_
#define _TESTTEMP_H_
template
class TestTemp
{
public:
TestTemp();
void SetValue( T obj_i );
T Getalue();
private:
T m_Obj;
};
#endif
Template Class Source File
// TestTemp.cpp
#include "TestTemp.h"
TestTemp::TestTemp()
{
}
void TestTemp::SetValue( T obj_i )
{
}
T TestTemp::Getalue()
{
return m_Obj;
}
If you try to implement the template class like a normal class implementation as shown above, it will generate a set of compilation errors such as
: error C2955: 'TestTemp' : use of class template requires template argument list
: error C2065: 'T' : undeclared identifier
REASON
In this case, the compiler doesn’t know about the object type. So it will not compile.
SOLUTION
To compile this class without any errors you need to put the template specific declaration in .cpp file also as shown below.
Sample Code:
Template Class Header File
// TestTemp.h
#ifndef _TESTTEMP_H_
#define _TESTTEMP_H_
template
class TestTemp
{
public:
TestTemp();
void SetValue( T obj_i );
T Getalue();
private:
T m_Obj;
};
#endif
Template Class Source File
// TestTemp.cpp
#include "TestTemp.h"
template
TestTemp
{
}
template
void TestTemp
{
}
template
T TestTemp
{
return m_Obj;
}
2. Linking
PROBLEM
With the above code, after resolving all the compilation error you may get some link errors while you create an object of this class in any file other than the TestTemp.cpp file.
Sample Code:
Client Source File
// Client.cpp
#include "TestTemp.h"
:
TestTemp
:
: error LNK2001: unresolved external symbol "public: __thiscall TestTemp
REASON
When the compiler does encounter a declaration of a TestTemp object of some specific type, e.g., int, it must have access to the template implementation source. Otherwise, it will have no idea how to construct the TestTemp member functions. And if you have put the implementation in a source (TestTemp.cpp) file and made it a separate part of the project, the compiler will not be able to find it when it is trying to compile the client source file. And #including the header file (TestTemp.h) will not sufficient at that time. That only tells the compiler how to allocate for the object data, and how to build the calls to the member functions, not how to build the member functions. And again, the compiler won’t complain. It will assume that these functions are provided elsewhere, and leave it to the linker to find them. So, when it’s time to link you will get "unresolved references" to any of the Class member functions that are not defined "inline" in the class definition.
SOULTION
There are different methods to solve this problem. You can select from any of these methods which is suitable for your application design.
METHOD1:
You can create the object of template class in the same file source file where it is implemented (TestTemp.cpp). So that there is no need to link the object creation code with its actual implementation in some other file. This will cause the compiler to compile these particular types, so the associated class member functions will be available at link time.
Sample Code:
Template Class Header File
// TestTemp.h
#ifndef _TESTTEMP_H_
#define _TESTTEMP_H_
template
class TestTemp
{
public:
TestTemp();
void SetValue( T obj_i );
T Getalue();
private:
T m_Obj;
};
#endif
Template Class Source File
// TestTemp.cpp
#include "TestTemp.h"
template
TestTemp
{
}
template
void TestTemp
{
}
template
T TestTemp
{
return m_Obj;
}
void TemporaryFunction ()
{
TestTemp
}
Client Source File
// Client.cpp
#include "TestTemp.h"
:
TestTemp
TempObj.SetValue( 2 );
int nValue = TempObj.Getalue();
:
No need to call this TemporaryFunction() function, it’s just to avoid link error.
METHODE 2
You can #include the source file that implements your template class in your client source file.
Sample Code:
Template Class Header File
// TestTemp.h
#ifndef _TESTTEMP_H_
#define _TESTTEMP_H_
template
class TestTemp
{
public:
TestTemp();
void SetValue( T obj_i );
T Getalue();
private:
T m_Obj;
};
#endif
Template Class Source File
// TestTemp.cpp
#include "TestTemp.h"
template
TestTemp
{
}
template
void TestTemp
{
}
template
T TestTemp
{
return m_Obj;
}
Client Source File
// Client.cpp
#include "TestTemp.h"
#include "TestTemp.cpp"
:
TestTemp
TempObj.SetValue( 2 );
int nValue = TempObj.Getalue();
:
METHODE 3
You can #include the source file that implements your template class (TestTemp.cpp) in your header file that defines the template class (TestTemp.h) and remove the source file from the project, not from the folder.
Sample Code:
Template Class Header File
// TestTemp.h
#ifndef _TESTTEMP_H_
#define _TESTTEMP_H_
template
class TestTemp
{
public:
TestTemp();
void SetValue( T obj_i );
T Getalue();
private:
T m_Obj;
};
#include "TestTemp.cpp"
#endif
Template Class Source File
// TestTemp.cpp
#include "TestTemp.h"
template
TestTemp
{
}
template
void TestTemp
{
}
template
T TestTemp
{
return m_Obj;
}
Client Source File
// Client.cpp
#include "TestTemp.h"
:
TestTemp
TempObj.SetValue( 2 );
int nValue = TempObj.Getalue();
: