# unresolved external symbol for a class using templates

## Recommended Posts

Shai    540
I'm trying to write a class for a binary heap using templates. The header file is pretty straightforward.
template <class T> class cBinaryHeap
{
private:
int amount;		//amount of elements in array
int	size;		//size of the array
T*	array;		//the array

public:
//constructor
cBinaryHeap(int Size);

//destructor
~cBinaryHeap(void);

//methods
T	GetFirst(void);
void	Print(void);
};

the definitions are in a separate file and look like this.
#include "cBinaryHeap.h"

//init
template <class T> cBinaryHeap<T>::cBinaryHeap(int Size)
{
//stuff
}

//destructor
template <class T> cBinaryHeap<T>::~cBinaryHeap(void)
{
//stuff
}

//add an element to the heap
template <class T> void cBinaryHeap<T>::Add(T element)
{
//stuff
}

//get the first element from the heap
template <class T> T cBinaryHeap<T>::GetFirst(void)
{
//stuff
}

//print the heap
template <class T> void cBinaryHeap<T>::Print(void)
{
//stuff
}

in my main.cpp I just go
#include "cBinaryHeap.h"
#include <iostream>
using namespace std;

int main()
{
cBinaryHeap<int> Heap(20);

{for(int i = 0; i < 20; i++)
{
}}

Heap.Print();

cin.get();
return 0;
}
The problem is that the linker gives a couple unresolved external symbol errors.
error LNK2001: unresolved external symbol "public: __thiscall cBinaryHeap<int>::~cBinaryHeap<int>(void)" (??1?$cBinaryHeap@H@@QAE@XZ) _main.obj : error LNK2001: unresolved external symbol "public: void __thiscall cBinaryHeap<int>::Print(void)" (?Print@?$cBinaryHeap@H@@QAEXXZ)
_main.obj : error LNK2001: unresolved external symbol "public: void __thiscall cBinaryHeap<int>::Add(int)" (?Add@?$cBinaryHeap@H@@QAEXH@Z) _main.obj : error LNK2001: unresolved external symbol "public: __thiscall cBinaryHeap<int>::cBinaryHeap<int>(int)" (??0?$cBinaryHeap@H@@QAE@H@Z)

Usually when I get a linker error I just figure I forgot a library. So this is first for me :/

##### Share on other sites
jfclavette    1058
The members of a template must be, as a general rule, in the header. Try putting everything in the .h

##### Share on other sites
Shai    540
it works :)

I can't see the member functions under ClassView then though :/ (MSVC++ 6.0)

##### Share on other sites
jfclavette    1058
Quote:
 Original post by Shaiit works :)I can't see the member functions under ClassView then though :/ (MSVC++ 6.0)

If you use MSVC 6.0, you should be happy that your templates work at all [grin]

##### Share on other sites
Boku San    428
xMcBaiNx is *sortof* correct. According to The Standard (TM), it should be possible to seperate header and implementation for templates using the export keyword; unfortunately, aside from Comeau, few-to-no compilers actually support the keyword.

As an alternative, you can "hack" support for templates into source files:
header.cpp#include "header.h"... //implementation details here

main.cpp#include ... //your normal includes, and then...#include "header.cpp"//now you need to provide a declaration using one of the types it will be//specialized for -- e.g., if you use the class specialized with floats,//place this somewhere at global scopetemplate <temp args> class Name<float> _nameFloat;

Contrived? Very. But it's the price we pay for non-compliance with The Standard.

NOTE: I'd love to guarantee the accuracy of this post, but at the moment I can't check on any of my personal files demonstrating this behavior -- my PSU decided to happily die on me recently.

EDIT: Before Fruny gets here, I'd like to say that I'm not entirely sure if it's necessary to declare this variable at global scope. I'd appreciate it if someone would test this type of declaration at local scope for me, because I can't put an IDE on this computer.

##### Share on other sites
Zahlman    1682
A better way is using .inl (for "inline" - or some other extension; it doesn't really matter) files:

// foo.h#ifndef FOO_H#define FOO_H// template declarations, and then at the end:#include "foo.inl"#endif// foo.inl// template implementations - the guy looking at the .h file doesn't have to see// this part, at least// foo.cpp#include "foo.h"// and proceed normally, without having to include a .cpp.