templates definition in .cpp file

Class Template vs Template Class :
An individual class defines how a group of objects can be constructed, while a class template defines how a group of classes can be generated.
Template class
is an instance of a class template.
template <typename T> std::vector<T> is not a class, for example. It is a template from which, if you supply an appropriate T, a class can be generated.

Why can’t I separate the definition of templates class from its declaration and put it inside a .cpp file?

instantiating a template, the compiler creates a new class with the given template argument

Example1:

template<typename T>

struct Foo

{
T bar;
void doSomething(T param) { // do stuff using T }
};

// in  .cpp
Foo<int> f;

When reading this line, the compiler will create a new class (let’s call it FooInt), which is equivalent to the following:

struct FooInt //this is decleration , it has to be defined in same //header file
{
int bar;
void doSomething(int param) { // do stuff using int }
}

Consequently, the compiler needs to have access to the implementation of the methods, to instantiate them with the template argument (in this case int). If these implementations were not in the header, they wouldn’t be accessible, and therefore the compiler wouldn’t be able to instantiate the template.

A common solution to this is to write the template declaration in a header file, then implement the class in an implementation file (for example .tpp), and include this implementation file at the end of the header.

In order for the compiler to generate the code, it must see both the template definition (not just declaration) and the specific types/whatever used to “fill in” the template. For example, if you’re trying to use a Foo<int>, the compiler must see both the Foo template and the fact that you’re trying to make a specific Foo<int>.

Example2:

Suppose you have a template Foo defined like this:
template<typename T>
class Foo {
public:
Foo();
void someMethod(T x);
private:
T x;
};

Along with similar definitions for the member functions:
template<typename T>
Foo<T>::Foo()
{

}

template<typename T>
void Foo<T>::someMethod(T x)
{

}

Now suppose you have some code in file Bar.cpp that uses Foo<int>:
// Bar.cpp

void blah_blah_blah()
{

Foo<int> f;
f.someMethod(5);

}

Clearly somebody somewhere is going to have to use the “pattern” for the constructor definition and for the someMethod() definition and instantiate those when T is actually int. But if you had put the definition of the constructor and someMethod() into file Foo.cpp, the compiler would see the template code when it compiled Foo.cpp and it would see Foo<int> when it compiled Bar.cpp, but there would never be a time when it saw both the template code and Foo<int>. So by rule #2 above, it could never generate the code for Foo<int>::someMethod().

Leave a Reply

Your email address will not be published. Required fields are marked *