Qt5 C++ Signal And Slots With Practical Examples #4
This is the sequel of my explaining the implementation details of the signals and slots.
In thewe have seen the general principle and how it works with the old syntax.
In this blog post, we will see the implementation details behind the new.
I already explained the advantages of the new syntax in a To summarize, the new syntax allows compile-time checking of the signals and slots.
It also allows automatic conversion of the arguments if they do not have the qt signals and slots with arguments types.
As a bonus, it enables the support for lambda expressions.
New overloads There was only a few changes required to make that possible.
The two other overloads are connecting a signal to a static function or a functor object without a receiver.
They are very similar and we will only analyze the first one in this article.
Pointer to Member Functions Source continuing my explanation, I would like to open a parenthesis to talk a bit about pointers to member functions.
Here is a simple sample code that declares a pointer to member function and calls it.
The good news is that you still do not really need to know much about them to use Qt and its new syntax.
These cryptic operators allow you to declare a pointer to a member or access it.
The type of such pointers includes the return type, the class which owns the member, the types of each argument and the const-ness of the function.
If the function varies slightly in signature, you cannot convert from one to the other.
A normal function pointer is just a normal pointer the address where the code of that function lies.
But pointer to member function need to store more information: member functions can be virtual and there is also an offset to apply to the hidden this in case of multiple inheritance.
This is why we need to take special care when manipulating them.
Type Traits: QtPrivate::FunctionPointer Let me introduce you to the QtPrivate::FunctionPointer type trait.
A trait is basically a helper class that gives meta data about a given type.
Another example of trait in Qt is.
What we will need to know in order to implement the new syntax is information about a function pointer.
The template struct FunctionPointer will give us information about T via its member.
It is a typedef to the class of which the function is a member.
It is a typedef to a meta-programming list.
Qt still supports C++98 compiler which means we unfortunately cannot require support for variadic templates.
Therefore we had to specialize our trait function for each number of arguments.
We have four kinds of specializationd: normal function pointer, pointer to member function, pointer to const member function and functors.
For each kind, we need to specialize for each number of arguments.
We support up to six arguments.
We also made a specialization using variadic template so we support arbitrary number of arguments if the compiler supports variadic templates.
The implementation of FunctionPointer lies in.
QObject::connect The implementation relies on a hoyle slots and of template code.
I am not going to explain all of it.
Skipped initialization of types, used for QueuedConnection.
They are pointers to typename FunctionPointer::Object instead.
This uses to make this overload only enabled for pointers to member functions because the Object only exists in FunctionPointer if the type is a pointer to member function.
We then start with a bunch of.
They should generate sensible compilation error messages when the user made a mistake.
We want to hide the underlying implementation from the user who should not need to care about it.
That means that if you ever you see a confusing error in the implementation details, it should be considered as a bug that.
We then allocate a QSlotObject that is going to be passed to connectImpl.
The QSlotObject is a wrapper around the slot that will help calling it.
It also knows the type of the signal arguments so it can do the proper type conversion.
QObject::connectImpl is the private internal function that will perform the connection.
It is similar to the original syntax, the difference is that instead of storing a method index in the QObjectPrivate::Connection structure, we store a pointer to the QSlotObjectBase.
It is a pointer to the member function pointer.
Yes, a pointer to the pointer Signal Index We need to make a relationship between the signal pointer and the signal index.
We use MOC for that.
Yes, that means this new syntax is still using the MOC and that there are no plans to get rid of it :.
The QSlotObjectBase QSlotObjectBase is the object passed to connectImpl that represents the slot.
It is re-implemented by one of the QSlotObject, QStaticSlotObject or QFunctorSlotObject template class.
Fake Virtual Table The problem with that is that each instantiation of those object would need to create a virtual table which contains not only pointer to virtual functions but also lot of information we do not need such as.
That would result in lot of superfluous data and relocation in the binaries.
In order to avoid that, QSlotObjectBase was changed not to be a C++ polymorphic class.
Virtual functions are emulated by hand.
The "re-implementations" set it to their own implementation in the constructor.
Please do not go in your code and replace all your virtual functions by such a hack because you read here it was good.
This is only done in this case because almost every call to connect would generate a new different type since the QSlotObject has template parameters wich depend on signature of the signal and the slot.
Protected, Public, or Private Signals.
Signals were protected in Qt4 and before.
It was a design choice as signals should be emitted by the object when its change its state.
They should not be emitted from outside the object and calling a signal on free play video slots casinos object is almost always a bad idea.
However, with the new syntax, you need to be able take the address of the signal from the point you make the connection.
The compiler would only let you do that if you have access to that signal.
In Qt 5 we had to change signals from protected to public.
This is unfortunate since this mean anyone can emit the signals.
We found no way around it.
We tried a trick with the emit keyword.
We tried returning a special value.
I believe that the advantages of the new syntax overcome the problem that signals are now public.
Sometimes it is even desirable to have the signal private.
This is the case for example in QAbstractItemModel, where otherwise, developers tend to emit signal from the derived class which is not what the API wants.
There used to be a pre-processor trick that made signals private but it broke the new connection syntax.
A new hack has been introduced.
It can be used as the last parameter of the signal.
Because it is private, only the object qt signals and slots with arguments the right to construct it for calling the signal.
MOC will ignore the QPrivateSignal last argument while generating signature information.
See free play video slots casinos an example.
More Template Code The rest of the code is in and.
It is mostly standard dull template code.
I will not go into much more details in this article, but I will just go over few items that are worth mentioning.
Meta-Programming List As pointed out earlier, FunctionPointer::Arguments free play video slots casinos a list of the arguments.
The code needs to operate on that list: iterate over each element, take only a part of it or select a given item.
That is why there is that can represent a list of types.
Some helpers to operate on it are andwhich give the N-th element in the list and a sub-list containing the N first elements.
The implementation of List is different for compilers that support variadic templates and compilers that do not.
With variadic templates, it is a template struct List.
The list of arguments is just encapsulated in the template parameters.
If the signal returns a value, it is a pointer to an object of the return type of the signal, else, it is 0.
If it returns void, we do nothing.
The problem is that it is not syntaxically correct to use the return value of a function that returns void.
Should I have duplicated the already huge amount of code duplication: what drilled and slotted rotors and pads something for the void return type and the other for the non-void?
No, thanks to the comma operator.
In C++ you can do something like that: functionThatReturnsVoidsomethingElse ; You could have replaced the comma by a semicolon and everything would have been fine.
Where it becomes interesting is when you call it with something that is not void: functionThatReturnsIntsomethingElse ; There, the comma will actually call an operator that you even can overload.
Then it can be used in each helper.
Conclusion This is it for this blog post.
There is still a lot to talk about I have not even mentioned QueuedConnection or thread safety yetbut I hope you found this interresting and that you learned here something that might help you as a programmer.
Woboq is a software company that specializes in development and consulting around Qt and Qt signals and slots with arguments />If you like this blog and want to read similar articles, consider subscribing Via Google Feedburner,Via Google Feedburner, or or.
Article posted by on 17 December 2012.
Qt: Signals and slots example (non-GUI)
Connecting in Qt 5. There are several ways to connect a signal in Qt 5. Old syntax. Qt 5 continues to support the old string-based syntax for connecting signals and slots defined in a QObject or any class that inherits from QObject (including QWidget)
In it something is. Many thanks for the help in this question, now I will know.
Bravo, what necessary words..., a remarkable idea
Silence has come :)
Quite right! It is good thought. I call for active discussion.
Has casually come on a forum and has seen this theme. I can help you council. Together we can come to a right answer.
It absolutely not agree
As much as necessary.
I confirm. It was and with me. Let's discuss this question. Here or in PM.
I consider, that you are not right. I am assured. Let's discuss. Write to me in PM, we will communicate.
Bravo, this remarkable idea is necessary just by the way