PDA

View Full Version : Templates and signals



Ubii
5th December 2010, 01:01
Hi!

Code:

Header


template <class D>
class Signal
: public QObject
{
public:
void signal(D);
signals:
void send(D);
};



cpp


template <class D> void Signal<D>::signal(D data)
{
emit send(data);
}




namespace plot{
Signal* xSignal;
}
//------------------------
plot::xSignal = new Signal();
QObject::connect(plot::xSignal, SIGNAL(send(double)), this, SLOT(notImportant(double)));


Everything still works to compile here but in next step something happend


double data = 0;
plot::xSignal->signal(data);

This code should send a signal to notImportant() like this:
First to "Signal::signal(double)" which send signal to "Signal::send(double)" which is connected to "notImportant(double)".
But I can't compile when I add the last line I got an error message.
Line:

plot::xSignal->signal(data);
Error message is:

error: undefined reference to `Signal<double>::signal(double)''

I am new to templates so it is propably someting wrong there.

Does any of you know whats wrong? :)

Thanks
Ubi

Sorry for my english, I am from Sweden :)

Timoteo
5th December 2010, 03:12
Did you not mean

plot::xSignal = new Signal<double>();
instead of

plot::xSignal = new Signal();

Also where is your constructor for Signal?

wysota
5th December 2010, 10:55
Just to warn you - Qt signals/slots mechanism is unable to cooperate with template classes.

Ubii
5th December 2010, 11:31
Did you not mean

plot::xSignal = new Signal<double>();
instead of

plot::xSignal = new Signal();

Also where is your constructor for Signal?

Yes, somehow chrome removed <double> so I used firefox instead and forgot to add it again.


Just to warn you - Qt signals/slots mechanism is unable to cooperate with template classes.

Thanks for the warning.
Then I do it in some other way :)

Timoteo
6th December 2010, 04:59
As an example of something you could do, I threw together some code real quick. This uses libsigc++.


template<typename rt, typename T> class EmittingObject
{
std::tr1::shared_ptr<T> t;
sigc::signal<rt> m_signal;
public:
EmittingObject()
{
t = std::tr1::shared_ptr<T>(new T);
}
sigc::signal<rt>& getSignal() { return m_signal; }
std::tr1::shared_ptr<T> object() { return t;}
};


/*class demonstrating a trivial connection*/
class XWidget : public EmittingObject<void, QWidget>, public sigc::trackable
{
void handle_signal()
{
this->object()->close();
}
public:
XWidget()
{
getSignal().connect(sigc::mem_fun(this, &XWidget::handle_signal));
}
void doSomethingToCauseAnEmit()
{
if(QMessageBox::question(object().get(), "Hello!", "Keep the widget open?", QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
getSignal().emit();
}
};

/*quick test piece*/
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
XWidget widget;
widget.object()->show();
while(widget.object()->isVisible())
{
widget.doSomethingToCauseAnEmit();
}
app.exit(0);
}

Sorry for the poor formatting, but that is Visual Assist's fault.

This is a silly example, I know. The basic concept is to sidestep Qt's signal/slot mechanism and employ another (if you truly need this type of thing, you may not!).

Ubii
6th December 2010, 16:27
As an example of something you could do, I threw together some code real quick. This uses libsigc++.


template<typename rt, typename T> class EmittingObject
{
std::tr1::shared_ptr<T> t;
sigc::signal<rt> m_signal;
public:
EmittingObject()
{
t = std::tr1::shared_ptr<T>(new T);
}
sigc::signal<rt>& getSignal() { return m_signal; }
std::tr1::shared_ptr<T> object() { return t;}
};


/*class demonstrating a trivial connection*/
class XWidget : public EmittingObject<void, QWidget>, public sigc::trackable
{
void handle_signal()
{
this->object()->close();
}
public:
XWidget()
{
getSignal().connect(sigc::mem_fun(this, &XWidget::handle_signal));
}
void doSomethingToCauseAnEmit()
{
if(QMessageBox::question(object().get(), "Hello!", "Keep the widget open?", QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
getSignal().emit();
}
};

/*quick test piece*/
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
XWidget widget;
widget.object()->show();
while(widget.object()->isVisible())
{
widget.doSomethingToCauseAnEmit();
}
app.exit(0);
}

Sorry for the poor formatting, but that is Visual Assist's fault.

This is a silly example, I know. The basic concept is to sidestep Qt's signal/slot mechanism and employ another (if you truly need this type of thing, you may not!).
Thanks for the example! Taught me a lot!

I'm not sure I will use it in this project though, because I don't really need it.

But I am sure it will be usefull in my other projects! :)

Timoteo
6th December 2010, 16:37
Glad you liked it, but like I said it is not meant to be a great example - just something to show what could be a great alternative if enough time is put into it (and a better design - composition would have been more appropriate than inheritance for example).