[SOLVED] Symbol(s) not found - template class
-
If I understand what I have read, the error "Symbol(s) not found" is a linking error somewhere in the code. Is that right?
My issue is that the compiler returned no line number or any other clue as to where the linking error might be located? So, how do I go about finding the compile error??
<EDIT>
Aha!! I found the error in my path finder class. Apparently, Qt is choking on the usage of my template class "BinaryHeap". I seem to remember reading somewhere that implementing templates in Qt is problematic. I sort of need a template heap class though.
Thoughts?
Laurence -
-
Hi,
as it's a linker error, there is no code line for that. The compiler creates object files from your source files. Those object files include references to external objects (in other object files or shared or static libs). These are resolved by the linker. If the linker comes to a symbol, he can't find, you get this error. But for all compilers I know, you get a bit more information so you should be able to find the missing library?
-
Check your compile output tab. It should have more information.
-
Thanks. I checked the compiler output and it seems that the template Headers are not being matched up with the implementation code in the CPP file. I did some reading and it seems that I can't split template header and implementation code between two files. So, I merged to the two into the CPP file.
I'm still getting the linking error. The code is below. Should I have merged them into the Header file?
When I use this template heap, I'm storing pointer information so, the code for that is the following.
//How I use the template
@
BinaryHeap<GraphNode*> m_bhOpen;
BinaryHeap<GraphNode*> m_bhClosed;
BinaryHeap<GraphNode*> m_bhPath;
@//The template implementation
@
#include <QtDebug>
#include <QVector>template<typename T>
class BinaryHeap
{private:
int m_iHeapSize;
QVector<T> m_vHeap;public:
BinaryHeap();
BinaryHeap(int heapsize);
~BinaryHeap();void SetSize(int heapsize); void Pop(); void Push(T nodeIndex); T Peek(); int Size();
};
//Ctor
template<typename T>
BinaryHeap<T>::BinaryHeap()
{
}//Ctor
template<typename T>
BinaryHeap<T>::BinaryHeap(int heapsize)
{
m_iHeapSize = heapsize;
m_vHeap.reserve(heapsize);
}//Dtor
template<typename T>
BinaryHeap<T>::~BinaryHeap()
{
}template<typename T>
void BinaryHeap<T>::SetSize(int heapsize)
{
m_vHeap.reserve(heapsize);
}//Pops a node off the heap
template<typename T>
void BinaryHeap<T>::Pop()
{
int index = 0;m_vHeap[index] = m_vHeap[(int)m_vHeap.size() - 1]; m_vHeap.pop_back(); int temp = m_vHeap[index]; int currentIndex = 0; int leftIndex = 0; int rightIndex = 0; while( index < (int)m_vHeap.size() / 2 ) { leftIndex = 2 * index + 1; rightIndex = leftIndex + 1; if(rightIndex < (int)m_vHeap.size() && m_vHeap[leftIndex] < m_vHeap[rightIndex]) currentIndex = rightIndex; else currentIndex = leftIndex; if( temp >= m_vHeap[currentIndex] ) break; m_vHeap[index] = m_vHeap[currentIndex]; index = currentIndex; }
}
//Pushes an element onto the heap
template<typename T>
void BinaryHeap<T>::Push(T nodeIndex)
{
//Add the new index to the heap
m_vHeap.push_back(nodeIndex);//Retrieve the index of the newly added value and it's parent index int index = (int)m_vHeap.size() - 1; int temp = m_vHeap[index]; int parentIndex = (index - 1) / 2; //Restack the heap as children cannot be larger than their parents while( index > 0 && temp >=m_vHeap[parentIndex] ) { m_vHeap[index] = m_vHeap[parentIndex]; index = parentIndex; parentIndex = (parentIndex - 1) / 2; }
}
//Peeks at the top most node
template<typename T>
T BinaryHeap<T>::Peek()
{
return m_vHeap[0];
}//Returns the size of the heap
template<typename T>
int BinaryHeap<T>::Size()
{
return (int)m_vHeap.size();
}@
-
Below is the compiler output where it's complaining about the Template Class.
Undefined symbols:
"BinaryHeap<GraphNode*>::Size()", referenced from:
PathFinder::FindPath(QString&, QString&)in pathfinder.o
PathFinder::FindPath(QString&, QString&)in pathfinder.o
"BinaryHeap<GraphNode*>::Push(GraphNode*)", referenced from:
PathFinder::FindPath(QString&, QString&)in pathfinder.o
"BinaryHeap<GraphNode*>::SetSize(int)", referenced from:
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
"BinaryHeap<GraphNode*>::BinaryHeap()", referenced from:
PathFinder::PathFinder()in pathfinder.o
PathFinder::PathFinder()in pathfinder.o
PathFinder::PathFinder()in pathfinder.o
PathFinder::PathFinder()in pathfinder.o
PathFinder::PathFinder()in pathfinder.o
PathFinder::PathFinder()in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
"BinaryHeap<GraphNode*>::~BinaryHeap()", referenced from:
PathFinder::~PathFinder()in pathfinder.o
PathFinder::~PathFinder()in pathfinder.o
PathFinder::~PathFinder()in pathfinder.o
PathFinder::~PathFinder()in pathfinder.o
PathFinder::~PathFinder()in pathfinder.o
PathFinder::~PathFinder()in pathfinder.o
PathFinder::~PathFinder()in pathfinder.o
PathFinder::~PathFinder()in pathfinder.o
PathFinder::~PathFinder()in pathfinder.o
PathFinder::~PathFinder()in pathfinder.o
PathFinder::PathFinder()in pathfinder.o
PathFinder::PathFinder()in pathfinder.o
PathFinder::PathFinder()in pathfinder.o
PathFinder::PathFinder()in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
PathFinder::PathFinder(Graph&)in pathfinder.o
ld: symbol(s) not found
collect2: ld returned 1 exit status -
[quote author="cazador7907" date="1292846909"]Thanks. I checked the compiler output and it seems that the template Headers are not being matched up with the implementation code in the CPP file. I did some reading and it seems that I can't split template header and implementation code between two files. So, I merged to the two into the CPP file.
I'm still getting the linking error. The code is below. Should I have merged them into the Header file?[/quote]
You should actually put all of your template-related code into headers files, not into cpp files.
http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12
-
Splitting the implementation of a template class into a separate .cpp file is difficult. You should copy the implementation into the header file and remove the separate .cpp file.
The (short) reason is this:
The compiler does not generate any code for the implementation in the .cpp. It cannot do this, because it does not know which actual type will be instantiated with the template. This is only known in the code which uses the template."Section 35.12":http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12 of the "C++ FAQ on templates":http://www.parashift.com/c++-faq-lite/templates.html explains the reasons en detail. Some reading in "this article":http://www.ecs.fullerton.edu/~sowell/cs331/TemplateClasses.html.
-
Problem solved!!
Thanks for the all of the super quick replies!
How do I go about marking this thread solved?