45

I have a problem in calling a template class I have. I declared a new type name Array, which is a template;

In the .hpp file:

template <typename T>
class Array
{
public:
   Array();
};

In the .cpp file:

template <typename T>
Array<T>::Array()
{
//Do something
}

In main:

Array<int> arr;

I get Linkage error: unresolved external symbol to the ctor.

Any Idea?

sth
  • 222,467
  • 53
  • 283
  • 367
Boris Raznikov
  • 2,373
  • 10
  • 34
  • 56
  • It's useful to link this question to https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file but it's not really a duplicate. OP didn't know something that was totally assumed in that question. – Winter Jun 22 '17 at 15:58

6 Answers6

83

Template functions, including member functions, must be written entirely in the header files. This means that if you have a template class, its implementation must be entirely in a header file. This is because the compiler needs to have access to the entire template definition (not just the signature) in order to generate code for each instantiation of the template.

Azeem
  • 11,148
  • 4
  • 27
  • 40
Tyler McHenry
  • 74,820
  • 18
  • 121
  • 166
  • yes it worked. Can you please add more explanation why you need to define all of it in the header ? In addition the implementation I added I added all before the "endif", right ? – Boris Raznikov Aug 30 '09 at 14:24
  • 1
    Correct. For a good explanation of why, see http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12 and the following question 35.13 that moonshadow linked to. – Tyler McHenry Aug 30 '09 at 14:29
  • 7
    Technically that is not a requirement. You can explicitly instantiate the template in some compilation unit and use that template elsewhere, but this needs quite a bit of manual housekeeping (adding explicit instantiations for each new type that is used in the project) that could even render it impossible (if you must work with yet unknown types). – David Rodríguez - dribeas Aug 30 '09 at 19:48
  • 1
    There is not only the use of templates as generic code. Templates are also used for coder generators, where you exactly know what variants you need (like "big endian", "little endian") – Johannes Schaub - litb Aug 31 '09 at 12:30
  • Are you ever going to incorporate the comments? Because this way the answer isn't that good. – Deduplicator May 11 '14 at 20:13
9

Put both the template declaration and the template function definitions in the header file. Most C++ compilers do not easily support the separate compilation model for templates,

7

If the definition of a templated function is not visible at the point where it is used (i.e. is not in the header or the same CPP file), you need to tell the compiler which instantiations to make.

moonshadow
  • 86,889
  • 7
  • 82
  • 122
5

The problem you have here is that you have hidden the definition of the constructor in the .cpp file. This definition applies to all types T, including T as an int that you use, but actually supplies no definitions whatsoever because its still only a declaration.
The linker cannot find the symbol Array<int>::Array().

Now, you can add a line like this:

Array<int> arr1;

to the end of your Array.cpp file and this makes the compiler instantiate the correct definition that the linker is looking for. However, this only supplies one definition, that of Array<int> and no other.

This solution will work, until you need an Array of a different template parameter, say, double, at which point you would need to add:

Array<double> arr2;

to the end of your Array.cpp file - now you can see how this is unsustainable!

If you need C++ to work with any type that you might want in the future, now is the time to move the definition of the ctor (and presumably all the other member functions) up into the header (and delete the .cpp file as it won't have anything left in it).

quamrana
  • 37,849
  • 12
  • 53
  • 71
1

Another answer, compile just your .cpp file (not the main) and check the size of the object file then create an empty.cpp file then compile that empty.cpp. finally compare the size of the both object files. You will see that they have the same size which means your .cpp file is nothing to compiler, so linker can not find anything.

mert inan
  • 1,537
  • 2
  • 15
  • 26
1

As mentioned above, in templates in C++ the process of new methods is executing by the compiler at compile time, the problem is that it needs to know all definition of thm during that time, so all class/function declaration must be ar h or hpp files.

Boris Raznikov
  • 2,373
  • 10
  • 34
  • 56