December 20, 2010

cazador7907 cazador7907
Lab Rat
78 posts

[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 –

 Signature 

Laurence -

 

11 replies

December 20, 2010

Gerolf Gerolf
Robot Herder
3287 posts

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?

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

December 20, 2010

QtK QtK
Lab Rat
1140 posts

Check your compile output tab. It should have more information.

December 20, 2010

cazador7907 cazador7907
Lab Rat
78 posts

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

  1.     BinaryHeap<GraphNode*> m_bhOpen;
  2.     BinaryHeap<GraphNode*> m_bhClosed;
  3.     BinaryHeap<GraphNode*> m_bhPath;

//The template implementation

  1. #include <QtDebug>
  2. #include <QVector>
  3.  
  4. template<typename T>
  5. class BinaryHeap
  6. {
  7.  
  8. private:
  9.     int m_iHeapSize;
  10.     QVector<T> m_vHeap;
  11.  
  12. public:
  13.     BinaryHeap();
  14.     BinaryHeap(int heapsize);
  15.     ~BinaryHeap();
  16.  
  17.     void SetSize(int heapsize);
  18.     void Pop();
  19.     void Push(T nodeIndex);
  20.     T Peek();
  21.     int Size();
  22. };
  23.  
  24. //Ctor
  25. template<typename T>
  26. BinaryHeap<T>::BinaryHeap()
  27. {
  28. }
  29.  
  30. //Ctor
  31. template<typename T>
  32. BinaryHeap<T>::BinaryHeap(int heapsize)
  33. {
  34.     m_iHeapSize = heapsize;
  35.     m_vHeap.reserve(heapsize);
  36. }
  37.  
  38. //Dtor
  39. template<typename T>
  40. BinaryHeap<T>::~BinaryHeap()
  41. {
  42. }
  43.  
  44. template<typename T>
  45. void BinaryHeap<T>::SetSize(int heapsize)
  46. {
  47.     m_vHeap.reserve(heapsize);
  48. }
  49.  
  50. //Pops a node off the heap
  51. template<typename T>
  52. void BinaryHeap<T>::Pop()
  53. {
  54.     int index = 0;
  55.  
  56.     m_vHeap[index] = m_vHeap[(int)m_vHeap.size() - 1];
  57.     m_vHeap.pop_back();
  58.  
  59.     int temp = m_vHeap[index];
  60.     int currentIndex = 0;
  61.     int leftIndex = 0;
  62.     int rightIndex = 0;
  63.  
  64.     while( index < (int)m_vHeap.size() / 2 )
  65.     {
  66.         leftIndex = 2 * index + 1;
  67.         rightIndex = leftIndex + 1;
  68.  
  69.         if(rightIndex < (int)m_vHeap.size() && m_vHeap[leftIndex] < m_vHeap[rightIndex])
  70.             currentIndex = rightIndex;
  71.         else
  72.             currentIndex = leftIndex;
  73.  
  74.         if( temp >= m_vHeap[currentIndex] )
  75.             break;
  76.  
  77.         m_vHeap[index] = m_vHeap[currentIndex];
  78.         index = currentIndex;
  79.     }
  80. }
  81.  
  82. //Pushes an element onto the heap
  83. template<typename T>
  84. void BinaryHeap<T>::Push(T nodeIndex)
  85. {
  86.     //Add the new index to the heap
  87.     m_vHeap.push_back(nodeIndex);
  88.  
  89.     //Retrieve the index of the newly added value and it's parent index
  90.     int index = (int)m_vHeap.size() - 1;
  91.     int temp = m_vHeap[index];
  92.     int parentIndex = (index - 1) / 2;
  93.  
  94.     //Restack the heap as children cannot be larger than their parents
  95.     while( index > 0 && temp >=m_vHeap[parentIndex] )
  96.     {
  97.         m_vHeap[index] = m_vHeap[parentIndex];
  98.         index = parentIndex;
  99.         parentIndex = (parentIndex - 1) / 2;
  100.     }
  101.  
  102. }
  103.  
  104. //Peeks at the top most node
  105. template<typename T>
  106. T BinaryHeap<T>::Peek()
  107. {
  108.     return m_vHeap[0];
  109. }
  110.  
  111. //Returns the size of the heap
  112. template<typename T>
  113. int BinaryHeap<T>::Size()
  114. {
  115.     return (int)m_vHeap.size();
  116. }

 Signature 

Laurence -

 

December 20, 2010

Volker Volker
Ant Farmer
5428 posts

Some code snippets and and the name(s) of the missing symbol(s) would help to investigate further.

Qt itself is not template averse in general, in fact there are many template classes in Qt.

December 20, 2010

Gerolf Gerolf
Robot Herder
3287 posts

Which compiler output do you get?

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

December 20, 2010

cazador7907 cazador7907
Lab Rat
78 posts

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

 Signature 

Laurence -

 

December 20, 2010

peppe peppe
Ant Farmer
1029 posts

cazador7907 wrote:
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?

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

 Signature 

Software Engineer
KDAB (UK) Ltd., a KDAB Group company

December 20, 2010

Volker Volker
Ant Farmer
5428 posts

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 [parashift.com] of the C++ FAQ on templates [parashift.com] explains the reasons en detail. Some reading in this article [ecs.fullerton.edu].

December 20, 2010

cazador7907 cazador7907
Lab Rat
78 posts

Problem solved!!

Thanks for the all of the super quick replies!

How do I go about marking this thread solved?

 Signature 

Laurence -

 

December 20, 2010

Volker Volker
Ant Farmer
5428 posts

Just go to the original post, on the right side, under your avatar and name is a link “edit”. There you can change the topic and prepend a [Solved].

December 20, 2010

Gerolf Gerolf
Robot Herder
3287 posts

Edit the first entry and change the title
If you want to close it, write a short notify to the mad scientiests or the trolls, then they close it.

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

 
  ‹‹ Problem with QThread..      Asynchronous drawing problems ››

You must log in to post a reply. Not a member yet? Register here!