views:

297

answers:

5

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?

+5  A: 

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,

anon
+8  A: 

Templates functions, including member functions, must be written entirely in headers. This means that if you have a template class, its implementation must be entirely in a header. 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.

Tyler McHenry
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 ?
Roman Dorevich
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
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
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
fuck me, 1 hour debug, silly mistake...
linjunhalida
+3  A: 

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
A: 

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
A: 

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.

Roman Dorevich