Cannot build a simple template
I've been all over google trying to understand why I can't get this to work
I've tried all kinds of things I've seen out there, even including the source file (ugh!) but whenever I'm not getting compiler errors, I'm getting linker errors.
OK, maybe I'm just a rube.
Anyway the code below is throwing this compiler exception.
LNK2019 unresolved external symbol public: virtual __thiscall ControlGroup<class QRadioButton> .. yada ... yada ... yada
Here is the code that declares an instance of the template in a header file.
bits.h
Code:
#include "controlgroup.h"
class Ui_bits
{
public:
ControlGroup<QRadioButton> *pBitSize;
}
Here's the call that invokes the template and incurs the wrath of the linker.
bits.cpp
Code:
#include "bits.h"
void some_init_func()
{
Twidget tw;
ui->pBitSizes = new ControlGroup <QRadioButton>(&tw, ui->centralWidget);
}
Here is the header for the offending template class...
controlgroup.h
Code:
#ifndef CONTROLGROUP_H
#define CONTROLGROUP_H
#include <QtCore>
#include <QtGui>
typedef void (*pf)(int);
class Twidget
{
public:
int count;
};
template <typename T>
class ControlGroup
: public QWidget{
public:
explicit ControlGroup
(Twidget
*tw,
QWidget *parent
=0) {
init (tw, parent );
}
ControlGroup(){};
void init
( Twidget
*tw,
QWidget *parent
);
~ControlGroup();
QList<T> widget;
private:
Twidget *m_tw;
#include "controlgroup.cpp"
};
#endif // CONTROLGROUP_H
... and here's the source ...
controlgroup.cpp
Code:
#ifndef CONTROLGROUP_CPP
#define CONTROLGROUP_CPP
#include "controlgroup.h"
template <typename T>
void init
( Twidget
*tw,
QWidget *parent
) {
for (int index = 0; index < tw->count; index++)
{
widget.append(new <T>(parent));
}
}
#endif
I'm sure it's something stupid, and that you guys frequently see ignorance like this.
It's probably a face-palmer, but I just can't figure it out.
Re: Cannot build a simple template
Code:
class ...
private: ...
#include "controlgroup.cpp"
};
To be honest, I've never seen anything like that before :) Especially that the "controlgroup.cpp" includes the file in which it is included.
Why dont you just define the template class in one single header ? I think you can get away from your linker issues this way easily.
Re: Cannot build a simple template
As a standard C/C++ coding practice templates have to be declared and defined in same header file.
You can still have separate h and cpp files, in your case do the following things, it should work
1. remove #include "controlgroup.h" from controlgroup.cpp file.
2. all other files(.h, .cpp,...) in the project should only include "controlgroup.h", nothing should include "controlgroup.cpp" (except controlgroup.h, which you already have)
Re: Cannot build a simple template
also, in the init() method :
Code:
widget.append(new <T>(parent));
does not make sense. T is a type, so allocating new object is more like :
Code:
widget.append(new T(parent));
plus, in your ControlGroup constructor, init() must be called as a templated method, so it should be :
Code:
init<T>(tw, parent );
third, make sure you import <QRadioButton> header where you need to.
Re: Cannot build a simple template
Quote:
Originally Posted by
totem
As a standard C/C++ coding practice templates have to be declared and defined in same header file.
Ah! I was not aware of that. Ok, I have moved all the template stuff into the header file, both the template class declaraton and its definition. Standard practice has its reasons, and its benefits.
Quote:
Originally Posted by
totem
also, in the init() method :
Code:
widget.append(new <T>(parent));
does not make sense. T is a type, so allocating new object is more like :
Code:
widget.append(new T(parent));
OK, I fixed that. Thank you!
Quote:
Originally Posted by
totem
plus, in your ControlGroup constructor, init() must be called as a templated method, so it should be :
Code:
init<T>(tw, parent );
When I did that, the compiler gave me "C2275: 'T': "Illegal use of this type as an expression.
Quote:
Originally Posted by
totem
third, make sure you import <QRadioButton> header where you need to.
Yes, I have this included. In fact I have many other classes that declare instances of QRadioButton, and I have no problems. Besides, the syntax highlighter is excellent at giving you clues about whether you have your declarations and definitions going well.
When I removed the offending <T>, even with the whole template class declaration and definition in the same from the init call, the linker still throws "2019: Unresolved externals ...".
If I uncomment this line in the init routine, I can't even compile.
Code:
widgetList.append(new T(parent));
This causes the compiler to emit C2664: void QList<T>::append(const T&) : cannot convert parameter1 from 'QRadioButton * to const QRadioButton const &).
I don't know why I should get that. I declare new QRadioButtons without penalty elsewhere.
Here is the whole controlgroup.h file as it exists now.
Code:
#ifndef CONTROLGROUP_H
#define CONTROLGROUP_H
#include <QtCore>
#include <QtGui>
#include <QtGui/QWidget>
#include <QtGui/QRadioButton>
enum direction_t { go_left, go_right };
typedef void (*pf)(int);
class Twidget
{
public:
QList <QLabel> labelList;
QList<QString> labelNames;
int count; // Number of widgets
QPoint start;
// Where to start the layout QPoint increment;
// how to lay these out direction_t direction; // go_left or go_right
};
template <typename T>
class ControlGroup
: public QWidget{
//Q_OBJECT
public:
explicit ControlGroup
(Twidget
*tw,
QWidget *parent
=0) {
init(tw, parent);
}
ControlGroup();
~ControlGroup();
QList<T> widgetList;
void init
( Twidget
*tw,
QWidget *parent
);
private:
Twidget *m_tw;
};
template <typename T>
void ControlGroup<T>
::init( Twidget
*tw,
QWidget *parent
) {
for (int index = 0; index < tw->count; index++)
{
widgetList.append(new T(parent));
tw
->labelList.
append(new QLabel(parent
));
}
}
#endif // CONTROLGROUP_H
Re: Cannot build a simple template
Well, I got it working.
The only thing I changed was I added empty curly brackets followed by a semicolon to the default constructor and the destructor.
I'm still very stumped why it wouldn't link and why the error messages were so obscure. I looked them up on google, but the information was sparse and laconic.
Thanks for all your help, though.