(C++) From Qt signal to Boost signal
January 9, 2018 · View on GitHub
(C++) 

From Qt signal to Boost signal
This article describes why and how to move from using Qt signals to using Boost signals.
Introduction
The first paragraph contains arguments why to move from Qt signals to Boost signals and when you might refrain from it. The second paragraph and beyond follow the transition in code for two very simple classes.
Why move from Qt signals to Boost signals?
My personal reasons for moving from Qt signals to Boost signals, are:
- When a library supports Boost, but conflicts with Qt
- Boost signals do not require the seperation of a class in a header (.h)file and implementation (.cpp) file (because Boost signals do not require the use of moc)
- Because the STL, TR1 and Boost libraries are 'the number one libraries' [1][2]
- I prefer using standard C++ keywords only
Arguments against moving from Qt signals to Boost signals are:
- The Qt signal syntax is easier to read and write
- When using only Qt, adding the Boost signals libraries increase compile time
The program's goal
The program implements two classes: an emitter and a receiver. After connecting the signals and slots, the emitter emits a signal, received by the receiver.
main should be:
int main() { //Create emitter //Create receiver //Connect emitter's signal to receiver //Let emitter emit its signal }
Screen output should be like:
Emitter: emitting signal Receiver: received signal
CppFromQtSignalToBoostSignal1: the ideal starting point
The code below would be the ideal starting point. But because moc requires the seperation of a class in a header (.h)file and implementation (.cpp) file, this code results in the link error undefined reference to 'vtable for [...]'. Due to this, next step is to seperate the class in a working example.
#include <iostream> #include <QObject> class QtEmitter : public QObject { Q_OBJECT public: void DoEmit() { std::clog << "QtEmitter: emitting signal\n"; emit signal_emit(); } signals: void signal_emit(); }; class QtReceiver : public QObject { Q_OBJECT public slots: void OnReceive() { std::clog << "QtReceiver: received signal\n"; } }; int main() { //Create emitter QtEmitter e; //Create receiver QtReceiver r; //Connect emitter's signal to receiver QObject::connect(&e,SIGNAL(signal_emit()),&r,SLOT(OnReceive())); //Let emitter emit its signal e.DoEmit(); }
CppFromQtSignalToBoostSignal2: the working starting point
The code below would be the working starting point. The next step is to replace the Qt signals by Boost signals.
main.cpp
#include "qtemitter.h" #include "qtreceiver.h" int main() { //Create emitter QtEmitter e; //Create receiver QtReceiver r; //Connect emitter's signal to receiver QObject::connect(&e,SIGNAL(signal_emit()),&r,SLOT(OnReceive())); //Let emitter emit its signal e.DoEmit(); }
qtemitter.cpp
#include <iostream> #include "qtemitter.h" void QtEmitter::DoEmit() { std::clog << "QtEmitter: emitting signal\n"; emit signal_emit(); }
qtemitter.h
#ifndef QTEMITTER_H #define QTEMITTER_H #include <QObject> class QtEmitter : public QObject { Q_OBJECT public: void DoEmit(); signals: void signal_emit(); }; #endif // QTEMITTER_H
qtreceiver.cpp
#include <iostream> #include "qtreceiver.h" void QtReceiver::OnReceive() { std::clog << "QtReceiver: received signal\n"; }
qtreceiver.h
#ifndef QTRECEIVER_H #define QTRECEIVER_H #include <QObject> class QtReceiver : public QObject { Q_OBJECT public slots: void OnReceive(); }; #endif // QTRECEIVER_H
CppFromQtSignalToBoostSignal3: the conversion to Boost signals
In the code below, the Qt signal is replaced by using a Boost signal. The next step is: can we put all this code in a single file?
emitter.cpp
#include <iostream> #include "emitter.h" void Emitter::DoEmit() { std::clog << "Emitter: emitting signal\n"; m_signal(); }
emitter.h
#ifndef EMITTER_H #define EMITTER_H #include <boost/signals2.hpp> struct Emitter { void DoEmit(); boost::signals2::signal<void ()> m_signal; }; #endif // EMITTER_H
main.cpp
#include "emitter.h" #include "receiver.h" int main() { //Create emitter Emitter e; //Create receiver Receiver r; //Connect emitter's signal to receiver e.m_signal.connect( boost::bind( &Receiver::OnReceive, r)); //Let emitter emit its signal e.DoEmit(); }
receiver.cpp
#include <iostream> #include "receiver.h" void Receiver::OnReceive() { std::clog << "Receiver: received signal\n"; }
receiver.h
#ifndef RECEIVER_H #define RECEIVER_H struct Receiver { void OnReceive(); }; #endif // RECEIVER_H
CppFromQtSignalToBoostSignal4: Boost signals in a single file
In the code below, all the code is placed a single file, and it works fine!
#include <iostream> #include <boost/signals2.hpp> struct Emitter { void DoEmit() { std::clog << "Emitter: emitting signal\n"; m_signal(); } boost::signals2::signal<void ()> m_signal; }; struct Receiver { void OnReceive() { std::clog << "Receiver: received signal\n"; } }; int main() { //Create emitter Emitter e; //Create receiver Receiver r; //Connect emitter's signal to receiver e.m_signal.connect( boost::bind( &Receiver::OnReceive, r)); //Let emitter emit its signal e.DoEmit(); }
Conclusion
There are reasons to move from using Qt signals to using Boost signals. This article shows that this is easy.
References
- Scott Meyers. Effective C++ (3rd edition). ISBN: 0-321-33487-6. Item 53: Familiarize yourself with the standard library, including TR1
- Scott Meyers. Effective C++ (3rd edition). ISBN: 0-321-33487-6. Item 54: Familiarize yourself with Boost