Click here to Skip to main content
15,867,594 members
Articles / Programming Languages / C++

How to Define a Template Class in a .h File and Implement it in a .cpp File

Rate me:
Please Sign up or sign in to vote.
4.47/5 (47 votes)
22 Dec 2009CPOL3 min read 567.7K   47   32
This article suggests three methods to implement template classes in a .cpp file.
The common procedure in C++ is to put the 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 it is compiled separately. But when we implement this procedure for template classes, some compilation and linking problems will arise. This article looks at three possible solutions with examples: You can create an object of a template class in the same source file where it is implemented, you can #include the source file that implements your template class in your client source file, and 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.

Introduction

This article suggests three methods to implement template classes in a .cpp file.

Background

The common procedure in C++ is to put the 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 it is compiled separately. But when we implement this procedure for template classes, some compilation and linking problems will arise.

Compilation Issue

Here is some sample code:

C++
// TestTemp.h 
#ifndef _TESTTEMP_H_
#define _TESTTEMP_H_
  
template<class T>
class TestTemp   
{
public:
    TestTemp();
    void SetValue( T obj_i );
    T Getalue();
 
private:
 
    T m_Obj;
};
#endif

// 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 a .cpp file, as shown below:

Template Class Header File
C++
// TestTemp.h
#ifndef _TESTTEMP_H_
#define _TESTTEMP_H_
 
template<class T>
class TestTemp  
{
 
public:
 
    TestTemp();
    void SetValue( T obj_i );
    T Getalue();
 
private:
 
    T m_Obj;
};
#endif
Template Class Source File
C++
// TestTemp.cpp
#include "TestTemp.h"
 
template <class T>
TestTemp<T>::TestTemp()
{
}
template <class T>
void TestTemp<T>::SetValue( T obj_i )
{
 
}
template <class T>
T TestTemp<T>::Getalue()
{
    return m_Obj;
}

Linking Issue

With the above code, after resolving all the compilation errors, you may get some link errors while you create an object of this class in any file other than TestTemp.cpp. Here is some sample code:

Client Source File
C++
// Client.cpp
#include "TestTemp.h"

    :
    TestTemp<int> TempObj;
    :
Link Error
: error LNK2001: unresolved external symbol "public: __thiscall
TestTemp<int>::TestTemp<int>(void)"
(??0?$TestTemp@H@@QAE@XZ)

Reason

When the compiler encounters 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, #includeing the header file (TestTemp.h) will not be 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.

Solution

There are different methods to solve this problem. You can select from any of the methods below depending on which is suitable for your application design.

Mehtod 1

You can create an object of a template class in the same source file where it is implemented (TestTemp.cpp). So, 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. Here is the sample code:

Template Class Header File
C++
// TestTemp.h
#ifndef _TESTTEMP_H_
#define _TESTTEMP_H_
template<class T>
class TestTemp  
{
public:
    TestTemp();
    void SetValue( T obj_i );
    T Getalue();
 
private:
    T m_Obj;
};
#endif
Template Class Source File
C++
// TestTemp.cpp
#include "TestTemp.h"
 
template <class T>
TestTemp<T>::TestTemp()
{
}
 
template <class T>
void TestTemp<T>::SetValue( T obj_i )
{
}
 
template <class T>
T TestTemp<T>::Getalue()
{
    return m_Obj;
}

// No need to call this TemporaryFunction() function,
// it's just to avoid link error.
void TemporaryFunction ()
{
    TestTemp<int> TempObj;
}
Client Source File
C++
// Client.cpp
#include "TestTemp.h"

    :
        TestTemp<int> TempObj;
        TempObj.SetValue( 2 );
        int nValue = TempObj.Getalue();
    :

The temporary function in "TestTemp.cpp" will solve the link error. No need to call this function because it's global.

Method 2

You can #include the source file that implements your template class in your client source file. Here is the sample code:

Template Class Header File
C++
// TestTemp.h
#ifndef _TESTTEMP_H_
#define _TESTTEMP_H_
 
template<class T>
class TestTemp  
{
public:
    TestTemp();
    void SetValue( T obj_i );
    T Getalue();
private:
    T m_Obj;
};
#endif
Template Class Source File
C++
// TestTemp.cpp
#include "TestTemp.h"

template <class T>
TestTemp<T>::TestTemp()
{
}
 
template <class T>
void TestTemp<T>::SetValue( T obj_i )
{
}
 
template <class T>
T TestTemp<T>::Getalue()
{
   return m_Obj;
}
Client Source File
C++
// Client.cpp
#include "TestTemp.h"
#include "TestTemp.cpp"
              :
        TestTemp<int> TempObj;
        TempObj.SetValue( 2 );
        int nValue = TempObj.Getalue();
              :

Method 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. Here is the sample code:

Template Class Header File
C++
// TestTemp.h
#ifndef _TESTTEMP_H_
#define _TESTTEMP_H_
template<class T>
class TestTemp  
{
public:
    TestTemp();
    void SetValue( T obj_i );
    T Getalue();
private:
    T m_Obj;
};
#include "TestTemp.cpp"

#endif
Template Class Source File
C++
// TestTemp.cpp
#include "TestTemp.h"

template <class T>
TestTemp<T>::TestTemp()
{
}
template <class T>
void TestTemp<T>::SetValue( T obj_i )
{
}
 
template <class T>
T TestTemp<T>::Getalue()
{
    return m_Obj;
}
Client Source File
C++
// Client.cpp
#include "TestTemp.h" 
               :
    TestTemp<int> TempObj;
    TempObj.SetValue( 2 );
    int nValue = TempObj.Getalue();
               :

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
PraiseNice Explanation Pin
Selay “selorey” Tekgül7-Aug-23 6:28
Selay “selorey” Tekgül7-Aug-23 6:28 
QuestionMethod 4 Pin
Binkie Boo13-Dec-21 2:27
Binkie Boo13-Dec-21 2:27 
This article has been extremely helpful as I was struggling to resolve the linkage error to which I thank you for providing the solution.

I have developed Method 4.

Rename the header file from "Template.h" to "Template.hpp" and alter the cpp include accordingly.

Create a new file "Template.h" with two lines which include both the hpp and cpp.

When the template class is to be used all that is needed is...
#include "Template.h"

I find this congruent with how classes are normally included.
I hope you see value in this.
QuestionLinking Error Solution is not working Pin
Ujjwal Gangwal26-Nov-19 5:25
professionalUjjwal Gangwal26-Nov-19 5:25 
PraiseNicely written article. Pin
Benktesh Sharma31-Jul-19 1:44
Benktesh Sharma31-Jul-19 1:44 
QuestionWhy remove from project in Method 3? Pin
Member 132729645-Oct-18 3:47
Member 132729645-Oct-18 3:47 
SuggestionThis works in Visual C++ Pin
mla15422-May-18 4:09
mla15422-May-18 4:09 
QuestionMethod 1 is the best as it will optimize the build . Pin
patoria6-Mar-18 22:13
patoria6-Mar-18 22:13 
QuestionGoogle says don't separate into forward declarations. Pin
Chal McCollough14-Jun-17 18:33
Chal McCollough14-Jun-17 18:33 
QuestionSituation where Method 2 works but Method 3 fails on G++ 4.9.3 on cygwin Pin
Member 1187223829-Jul-15 7:18
Member 1187223829-Jul-15 7:18 
AnswerRe: Situation where Method 2 works but Method 3 fails on G++ 4.9.3 on cygwin Pin
Member 1187223829-Jul-15 7:40
Member 1187223829-Jul-15 7:40 
Questionerror Pin
Member 1164279224-Jul-15 9:17
Member 1164279224-Jul-15 9:17 
SuggestionMethod 4 (similar to method 2) Pin
ddCubinator8-Jul-15 2:42
ddCubinator8-Jul-15 2:42 
QuestionBeginner's question Pin
Member 117335721-Jun-15 7:42
Member 117335721-Jun-15 7:42 
GeneralMy vote of 5 Pin
Member 1101076613-Aug-14 4:49
Member 1101076613-Aug-14 4:49 
Question[My vote of 2] Please use the right vocabulary Pin
feraudy3-May-14 1:10
feraudy3-May-14 1:10 
GeneralMy vote of 5 Pin
Member 987058311-Jun-13 11:30
Member 987058311-Jun-13 11:30 
SuggestionAnd an elegant architecture for organizing C++ header files of template classes Pin
Khaari15-Apr-13 19:03
professionalKhaari15-Apr-13 19:03 
SuggestionMethod 4 (Another method) Pin
Siddharth Hegde19-Dec-12 1:09
Siddharth Hegde19-Dec-12 1:09 
GeneralRe: Method 4 (Another method) Pin
Khaari6-Apr-13 22:00
professionalKhaari6-Apr-13 22:00 
QuestionMethod 3 requires inline Pin
E.Hyde4-Sep-12 23:59
E.Hyde4-Sep-12 23:59 
GeneralNice article Pin
rajajay8218-Jan-10 0:04
rajajay8218-Jan-10 0:04 
GeneralI don't like those solutions Pin
Odys!23-Dec-09 12:00
Odys!23-Dec-09 12:00 
AnswerSome comments to your ideas: Pin
dtr2223-Dec-09 8:59
dtr2223-Dec-09 8:59 
GeneralRe: Some comments to your ideas: Pin
Febil Chacko Thanikal23-Dec-09 15:45
Febil Chacko Thanikal23-Dec-09 15:45 
GeneralI don't like any of these solutions. Pin
millerize23-Dec-09 6:04
millerize23-Dec-09 6:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.