tags:

views:

64

answers:

1

Linking my program produces a bunch of errors like below.

/home/starlon/Projects/LCDControl/DrvQt.cpp:8: undefined reference to `Generic<LCDText>::Generic(Json::Value*, int)'
/home/starlon/Projects/LCDControl/DrvQt.cpp:18: undefined reference to `Generic<LCDText>::~Generic()'
/home/starlon/Projects/LCDControl/DrvQt.cpp:8: undefined reference to `Generic<LCDText>::Generic(Json::Value*, int)'
/home/starlon/Projects/LCDControl/DrvQt.cpp:18: undefined reference to `Generic<LCDText>::~Generic()'
DrvQt.o: In function `~DrvQt':
/home/starlon/Projects/LCDControl/DrvQt.cpp:23: undefined reference to `Generic<LCDText>::~Generic()'
/home/starlon/Projects/LCDControl/DrvQt.cpp:23: undefined reference to `Generic<LCDText>::~Generic()'
/home/starlon/Projects/LCDControl/DrvQt.cpp:23: undefined reference to `Generic<LCDText>::~Generic()'
/home/starlon/Projects/LCDControl/DrvQt.cpp:23: undefined reference to `Generic<LCDText>::~Generic()'
DrvQt.o:(.rodata._ZTV5DrvQt[vtable for DrvQt]+0xc): undefined reference to `Generic<LCDText>::CFG_Key()'
DrvQt.o:(.rodata._ZTC5DrvQt0_7GenericI7LCDTextE[vtable for DrvQt]+0xc): undefined reference to `Generic<LCDText>::CFG_Key()'

Does that mean I have to have a Generic::MethodName (and Generic::MethodName) for every template parameter I'm going to use? I hope not. I was under the impression that templates were supposed to avoid that sort of scenario.

Edit: Here's DrvQt.cpp

#include <iostream>
#include <QMainWindow>
#include "LCDControl.h"
#include "DrvQt.h"

DrvQt::DrvQt(LCDControl *visitor, Json::Value *config, int rows, int cols) :
    Generic<LCDText>(config, LCD_TEXT) { // line 8
    display_ = new QtDisplay((Generic<LCDText> *)this,
        config, rows, cols, 8, 6);
    lcd_ = (LCDText *)display_;
    std::cout << "DrvQt" << std::endl;
    visitor_ = visitor;
    std::cout << "Eval: " << Eval("uptime.Uptime('%H')").toString().toStdString() << std::endl;
    std::cout << "Eval: " << Eval("cpuinfo.Cpuinfo('model name')").toString().toStdString() << std::endl;
    std::cout << "Eval: " << Eval("foo").toString().toStdString() << std::endl;
    std::cout << "Eval: " << Eval("name").toString().toStdString() << std::endl;
} // line 18

DrvQt::~DrvQt() {
    delete display_;
    //delete window;
} // line 23
+4  A: 

More code to debug would be nice, please post some code as that debug message is not enough to go with (for me atleast).

For now, It sounds like an undefined reference so you might want to make sure that the declaration and implementation of the template class is in the same file. Not separated into a .hpp and .cpp as usual. This is a shortcoming of template classes (that makes sense once you understand how they work).

Edit: How are you supposed to use template classes in other files?

I mean if you have (in a normal project):

someclass.hpp
someclass.cpp
main.cpp

And then you make someclass a template class then you must merge all of the implementation of someclass into its header file so it would now be:

someclass.hpp
main.cpp

In both situations you can still have a #include "someclass.hpp" in the main.cpp file and get access to that class both times.

For more information look at the bottom paragraph here (cppreference).

Robert Massaioli
Well that doesn't make sense. How are you supposed to use template classes in other files?
Scott
@Scott: You put the entire code for the template class in the .hpp.
Mark Ransom
And make free functions inline where necessary.
Georg Fritzsche
Edited my answer to include an explanation.
Robert Massaioli
Ok I see. How do libraries get around that? Or is it too much of a hassle to wrap templated libraries in other languages?
Scott
Most libraries separate the two my having an #include "implelentationFile.tcc" at the bottom of the header file. So the implementation and definition are in two different files but are seen by the compiler to be in the same file.
Robert Massaioli
Well, putting it all in one file fixed it. Thanks, Shhnap.
Scott