Henste93
Henste93

Reputation: 303

Compiler picks wrong overloaded function

I'm about to adapt my sources to the new signals and slots syntax in Qt. While the below stated code functioned well with a deprecated const char* signal parameter, it doesn't work with the new QMetaMethod &signal syntax.

class SignalWaiter : public QObject {
    Q_OBJECT
public:
    SignalWaiter(const QObject* sender, const QMetaMethod &signal);

private slots:
    void signalCaught();
};

SignalWaiter::SignalWaiter(const QObject* sender, const QMetaMethod &signal) {
    QObject::connect(sender, signal, this, &SignalWaiter::signalCaught);
}

void SignalWaiter::signalCaught() {
}

The compiler stops at the connect() command with the message:

error: C2664: 'QMetaObject::Connection QObject::connect(const QObject *,const char *,const char *,Qt::ConnectionType) const': cannot convert argument 2 from 'const QMetaMethod' to 'const char *'

and

No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called

So obviously the compiler tries to call the overloaded connect method with the old syntax. What am I doing wrong?

Upvotes: 1

Views: 1368

Answers (3)

O'Neil
O'Neil

Reputation: 3849

The connect() you're trying to use has the signature:

QMetaObject::Connection QObject::connect(
    const QObject *sender, 
    const QMetaMethod &signal,
    const QObject *receiver,
    const QMetaMethod &method,
    Qt::ConnectionType type = Qt::AutoConnection)

note the 4th parameter const QMetaMethod &method which is not a pointer to member, which is why you get an error.

To do the appropriate convertion, you can use:

auto metaSlot = metaObject()->method(metaObject()->indexOfSlot("signalCaught()"));
QObject::connect(sender, signal, this, metaSlot);

Though, as pointed out by @p-a-o-l-o, new signal/slot syntax uses pointers to member functions, not QMetaMethod. His solution might be what you're really looking for.

Upvotes: 5

Henste93
Henste93

Reputation: 303

Changing

QObject::connect(sender, signal, this, &SignalWaiter::signalCaught);

to

QObject::connect(sender, signal, this, QMetaMethod::fromSignal(&SignalWaiter::signalCaught));

worked for me, which is similar to O'Neil's answer, but a little shorter syntax-wise. Note that you need to wrap the signal parameter in every constructor call in a QMetaMethod::fromSignal() command as well.

The solution proposed by p-a-o-l-o didn't work for me, because my SignalWaiter class actually inherits from QObject, which forbids the use of templates.

Upvotes: 0

p-a-o-l-o
p-a-o-l-o

Reputation: 10047

I think O'Neil answer solves the compilation issue, but if the OP really wants to

adapt my sources to the new signals and slots syntax

maybe they want to give the SignalWaiter class another constructor, like this:

template<typename T>
SignalWaiter(const T* sender, void (T::* signal)())
{
    QObject::connect(sender, signal, this, &SignalWaiter::signalCaught);
}

Having a class MyClass with a void mysignal() signal:

MyClass * myclass = new MyClass();
SignalWaiter * waiter = new SignalWaiter(myclass, &MyClass::mysignal);

Upvotes: 3

Related Questions