Slot & signal argument count difference - how to deal with?
-
Good morning,
I have a rather general question related to the topic.I have a slot function like this:
void MyClass::request(const QString &arg = QString());
where inside I make a choice based onarg.isEmpty()
.Now when I try to make a connection like this:
connect(ui->edit,&QLineEdit::returnPressed,this,&MyClass::request);
compiler throws out an error (shortened version):error: static assertion failed due to requirement 'int(FunctionPointer<void (QLineEdit::*)()>::ArgumentCount) >= int(FunctionPointer<void (MyClass::*)(const QString &)>::ArgumentCount)': The slot requires more arguments than the signal provides. static_assert(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount), ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Usually I deal with it by wrapping the connect into lambda so it is not a stopping issue but I was just wondering - can this be done differently? The argument missing from the signal does not matter as it becomes a QString() anyway.
Many thanks in advance.
-
Good morning,
I have a rather general question related to the topic.I have a slot function like this:
void MyClass::request(const QString &arg = QString());
where inside I make a choice based onarg.isEmpty()
.Now when I try to make a connection like this:
connect(ui->edit,&QLineEdit::returnPressed,this,&MyClass::request);
compiler throws out an error (shortened version):error: static assertion failed due to requirement 'int(FunctionPointer<void (QLineEdit::*)()>::ArgumentCount) >= int(FunctionPointer<void (MyClass::*)(const QString &)>::ArgumentCount)': The slot requires more arguments than the signal provides. static_assert(int(SignalType::ArgumentCount) >= int(SlotType::ArgumentCount), ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Usually I deal with it by wrapping the connect into lambda so it is not a stopping issue but I was just wondering - can this be done differently? The argument missing from the signal does not matter as it becomes a QString() anyway.
Many thanks in advance.
@artwaw thats what QOverload is for:
-
@artwaw thats what QOverload is for:
-
A artwaw has marked this topic as solved on
-
@J-Hilk Thank you. I was vaguely aware of its existence but never used. Will learn to use that.
@artwaw
I do not believe @J-Hilk's suggestion ofqOverload()
is for this case/works here (unless he corrects me/knows better). It is for distinguishing between multiple potential slot functions to connect to a signal where there is more than one overload for the slot. This is not your issue here.connect(ui->edit, &QLineEdit::returnPressed, this, qOverload<const QString &>(&MyClass::request));
gives me the same error as you get now. All tested with Qt5.15 and
g++ -c -std=gnu++1z
(gcc 11.4).I believe that you cannot directly call a slot method which has an extra argument over what the signal sends, even if the slot specifies a default for that argument to make it "optional". I believe you need to connect with a lambda to achieve that.
connect(ui->edit, &QLineEdit::returnPressed, this, [this]() { request(); });
Somewhat oddly, it seems that you can even connect to "extra default arg" if you do it in-line via a lambda:
connect(ui->edit, &QLineEdit::returnPressed, this, [this](const QString &arg = QString() ){});
is accepted. But if you try to put a method (with an optional argument) there it errors. One would have thought they would be equivalent, but apparently not. If a C++ expert would care to comment on this difference I should be interested :)
-
@artwaw
I do not believe @J-Hilk's suggestion ofqOverload()
is for this case/works here (unless he corrects me/knows better). It is for distinguishing between multiple potential slot functions to connect to a signal where there is more than one overload for the slot. This is not your issue here.connect(ui->edit, &QLineEdit::returnPressed, this, qOverload<const QString &>(&MyClass::request));
gives me the same error as you get now. All tested with Qt5.15 and
g++ -c -std=gnu++1z
(gcc 11.4).I believe that you cannot directly call a slot method which has an extra argument over what the signal sends, even if the slot specifies a default for that argument to make it "optional". I believe you need to connect with a lambda to achieve that.
connect(ui->edit, &QLineEdit::returnPressed, this, [this]() { request(); });
Somewhat oddly, it seems that you can even connect to "extra default arg" if you do it in-line via a lambda:
connect(ui->edit, &QLineEdit::returnPressed, this, [this](const QString &arg = QString() ){});
is accepted. But if you try to put a method (with an optional argument) there it errors. One would have thought they would be equivalent, but apparently not. If a C++ expert would care to comment on this difference I should be interested :)
@JonB you're right, this is with default arguments in the slot functions, didn't see that.
Thats tricky and there's only really 3 ways to do this:
class MyClass2 : public QObject { Q_OBJECT public: MyClass2(QObject *parent = nullptr) : QObject(parent) { //1 Lambda connect(this, &MyClass2::mySignal, this, [this]() { request(); }); //2other slot connect(this, &MyClass2::mySignal, this, &MyClass2::requestVanialla); //3 binds connect(this, &MyClass2::mySignal, std::bind(&MyClass2::request, this, QLatin1String())); } signals: void mySignal(); public slots: void request(const QString & request = QLatin1String()) { //do Stuff here qDebug() << request; } void requestVanialla() {request();} };
-
Thank you, Gentlemen. I indeed ran into a method "ambiguous" error while trying with qOverload but since I've been using lambdas (as signposted "1 Lambda" in the post above) I decided to investigate that later on under the assumption I misunderstood something. Now it is clear I did not :)
At any rate, I learned something new from your answers today and am grateful.
Have a lovely day!