1

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?

max66
  • 65,235
  • 10
  • 71
  • 111
  • missing `};` for `Class1` is probably a typo - right? Otherwise your code is fine, as long as you put Class1 and its method definitions in header file. – marcinj Jul 20 '16 at 11:42
  • Thx for the fast answer. Yes the }; i forgot to write here. I have it in my code. class and method prototype are in header file. the rest is in cpp file. – JOnathanJOnes Jul 20 '16 at 11:47
  • 1
    Since you split your template code across multiple source files, my guess is that you are trying to use the template in a translation unit that is unaware of the said template's members definitions – Rerito Jul 20 '16 at 11:48
  • @Byteventurer Not if the definitions are in a `.cpp` file that specifies explicit instantiations. Oh good, now it's deleted, and I'm talking to myself. This was in response to the assertion that definitions _must_ be put in a header file. That's not true. _Many_ of them must, but it's not a strict rule, if you know ahead of time what you need. – underscore_d Jul 20 '16 at 11:53
  • 2
    Possible duplicate: [Why can templates only be implemented in the header file?](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – NathanOliver Jul 20 '16 at 11:55
  • I have to make something clear. When i use my code for example with int by: Class1 it works very well as soon i use Class1 the linker does not find it as long as i do not give the spcialisation to the code. But i need a solution without spcialisation. – JOnathanJOnes Jul 20 '16 at 12:01
  • I suggest you edit your answer to show us a real minimum example with your file configuration: template header, template "cpp" file, test case "cpp" file... – Rerito Jul 20 '16 at 12:14

2 Answers2

6

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.

Rerito
  • 5,886
  • 21
  • 47
  • When i use my code for example with int by: Class1 it works very well as soon i use Class1 the linker does not find it as long as i do not give the spcialisation to the code. But i need a solution without spcialisation. – JOnathanJOnes Jul 20 '16 at 12:12
  • @JOnathanJOnes That's probably your compiler being too generous in situations where it can do so. The proper, portable way to make a templated class is to expose all the definitions in the header file. – KABoissonneault Jul 20 '16 at 12:33
  • TMP means either temp, Template MetaProgramming or Thermomechanical Pulp (well, I admit there's loads of other meanings) but using it to mean "template" is a bit of a stretch... – rubenvb Jul 20 '16 at 12:47
1

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.

max66
  • 65,235
  • 10
  • 71
  • 111