-1

I'm struggling with getting template specialization to work. Even with this simple example code it won't work.

PriorityQueue.h

template<class T>
class PriorityQueue {

public:

    T remove();

};

template<>
class PriorityQueue<string> : public PriorityQueue<string> {

public:

    string remove();

};

PriorityQueue.cpp

string PriorityQueue<string>::remove() {
    //implementation
}

I get this error message:

.../PriorityQueue.h39:38: error: :39:38: error: base class has incomplete type
base class has incomplete type
class PriorityQueue<string> : public PriorityQueue<string> {class PriorityQueue<string> : public PriorityQueue<string> {

                              ~~~~~~~^~~~~~~~~~~~~~~~~~~~~                              ~~~~~~~^~~~~~~~~~~~~~~~~~~~~

EDIT

I've now changed the header to only specialize the member function, but still get errors. I should probably show you the whole code, so here's a link to the project on Github with the recent updated code.

This is the new error message:

duplicate symbol __ZN13PriorityQueueINSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEE6removeEv in:
    CMakeFiles/Oblig2_Oppg2.dir/main.cpp.o
    CMakeFiles/Oblig2_Oppg2.dir/PriorityQueue.cpp.o
ld: 1 duplicate symbol for architecture x86_64
Ferdinand
  • 35
  • 6

1 Answers1

3

Your specialisation is defined with a recursive inheritance. This can't work:

class PriorityQueue<string> : public PriorityQueue<string> 

If you want to specialize, you don't need to make it inheriting from itself. This should be sufficient:

template<>
class PriorityQueue<string> {
   ...
}

If you specialize a template class, you have to provide everything it contains. However, if you want only to specialize the remove() member, do it as follows:

template<>
string PriorityQueue<string>::remove() { /* your code there */ }

Live demo

Christophe
  • 68,716
  • 7
  • 72
  • 138
  • I've tried that aswell. By doing so, I'm also not able to reach other methods declared in the first PriorityQueue-class. – Ferdinand Mar 13 '16 at 21:49
  • 3
    @Ferdinand That's because the two are unrelated. `PriorityQueue` is a separate type that only shares a name with `PriorityQueue`. It doesn't share any members and there is no hierarchical relationship. – Barry Mar 13 '16 at 21:52
  • @Ferdinand if there are "other methods in the first class" then you're not providing us enough information to answer your question. – xaxxon Mar 13 '16 at 21:53
  • @Ferdinand I've edited the answer to show you how you could specialize just one member function – Christophe Mar 13 '16 at 21:56
  • @Barry ahh, good to know. But now I get this error message: `duplicate symbol __ZN13PriorityQueueINSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEEE6removeEv in: CMakeFiles/Oblig2_Oppg2.dir/main.cpp.o CMakeFiles/Oblig2_Oppg2.dir/PriorityQueue.cpp.o ld: 1 duplicate symbol for architecture x86_64` Here's a [link](https://github.com/Ferdizz/Oblig2_Oppg2) to the project on Github if necessary. – Ferdinand Mar 13 '16 at 22:21
  • @Ferdinand that has nothing to do with the code, but with your makefile: you have template split over a PriorityQueue.h and a PriorityQueue.cpp. You include the .cpp into main.cpp. So when compiling main.cpp, the object file already contains the implementation of the specialization. Unfortunately, you also compile PriorityQueue.cpp separately so that the specialization also gets defined there. So the linker finds to versions for the same implementation. get rid of PriorityQueue.cpp and put all this into the header. – Christophe Mar 13 '16 at 22:48
  • 1
    Declare the specialization in the header file. Define the specialization in one of your cpp files. – Sam Varshavchik Mar 13 '16 at 22:49
  • @Christophe This got it working, thanks! But implementing in the header file is considered bad practice as far as i know? There is no other/better way to solve this issue? – Ferdinand Mar 13 '16 at 23:12
  • @Ferdinand this applies to non template classes. You could have a look at [this answer](http://stackoverflow.com/a/19798414/3723423) which explains the details. – Christophe Mar 13 '16 at 23:28