JOnathanJOnes
JOnathanJOnes

Reputation: 109

How to use a class as parameter in templates in C++

A: I use something like this:

In Class1.h:

template <class T>
class Class1 : Database {
public:
    Class1();
};

In Class1.cpp:

#include "Class1.h"

template <typename T>
Class1<T>::Class1(){
   //Some code
}

Calling class:

#include "Class1.h"

Class1<Class2> *class1 = new Class1<Class2>();

If i run this, the linker is not able to find "Class1".

B: When i use something like this:

#include "Class1.h"

template <> Class1<Class2>::Class1(){}

The linker is able to find it.

My problem is, that i need to use A in my code and not B.

That means i don't want to use:

template <> Class1<Class2>::Class1(){}

I Want to use ONLY:

template <typename T>
Class1<T>::Class1(){
   //Some code
}

All tutorials say that i use it correctly and it has to work. Can anybody help me?

Upvotes: 1

Views: 143

Answers (2)

Rerito
Rerito

Reputation: 6086

When you try to instantiate a specialization of a class template, the compiler needs to have access to every member definition, otherwise it is unable to generate the corresponding code (a C++ template is basically a copypasta factory on steroids).

Since you split the implementation details into a separate file, you cannot instantiate your specific specialization a.k.a. Class1<Class2>. I suppose you put the template <> Class1<Class2>::Class1() {} bit in the header file? If so, your code compiles because it has a full specialization for Class2 with an available constructor when you use it in your sample.

Schematically you have:

Template Header -> included in -> test sample cpp file
\-----------------------> included in -> Template Implementation cpp file

You can see that all the actual implementations for your template are not reachable within your test sample translation unit.

Upvotes: 6

max66
max66

Reputation: 66190

As said in comments, Class1 is a templated class, so you should put you contructor in the header file, not in a separated cpp file. Otherwise, you can put the constructor in the cpp file where you use it, but only if you use it only in a single cpp file.

The problem is that when you write

Class1<Class2> *class1 = new Class1<Class2>();

you're asking the compiler to call (and construct) a constructor for Class1<Class2> but the compiler don't know how to construct it because it's defined in another file (the compiler, in this phase, see only "Class1.h"; doesn't know the content of "Class1.cpp").

Your solution B

template <> Class1<Class2>::Class1(){}

works because you're defining a constructor specialization for Class1<Class2>, so the compiler know it

Solution: delete

template <typename T>
Class1<T>::Class1(){
   //Some code
}

from "Class1.cpp" and put it in "Class1.h".

p.s.: sorry for my bad English.

Upvotes: 1

Related Questions