Qt - Compile-time check if qRegisterMetaType<T>() was called

334 views Asked by At


Question: Is there a way to check at compile-time if qRegisterMetaType<T>() was called for a custom type T?


The custom type T needs to be registered in Qt meta-type system in order to be used in e.g. queued connections.

If such a connection is made, and a signal triggered, the runtime warning will be shown:

QObject::connect: Cannot queue arguments of type 'T'
(Make sure 'T' is registered using qRegisterMetaType().)

This is hard to track, so I would prefer to check this at compile-time. Is that in any way possible?

(I understand that if it was possible, it would probably already be a part of Qt Framework itself, but maybe...?)


Note: I know I can check if a type was declared as metatype (Check if type is declared as a meta type system (for SFINAE)), but this doesn't solve my problem.


The code example would be:

#include <QCoreApplication>
#include <QDebug>
#include <QMetaMethod>
#include <QObject>
#include <QThread>
#include <QTimer>


struct Payload {
    Payload() = default;
};
// Type is declared as metatype
Q_DECLARE_METATYPE(Payload) 


class ObjectOne : public QObject {
    Q_OBJECT
public:
    using QObject::QObject;
    void emitPayloadChanged() { Payload p; emit payloadChanged(p); }
signals:
    void payloadChanged(const Payload& p);
};


class ObjectTwo : public QObject {
    Q_OBJECT
public:
    using QObject::QObject;

    void handlePayload(const Payload& p) { qDebug() << "handling payload"; }
};


int main(int argc, char* argv[]) {
    QCoreApplication app(argc, argv);

    // Uncommenting the following line fixes the runtime warning
    // qRegisterMetaType<Payload>();  

    QThread t1, t2;

    ObjectOne o1;
    o1.moveToThread(&t1);

    ObjectTwo o2;
    o2.moveToThread(&t2);

    t1.start();
    t2.start();

    QObject::connect(&o1, &ObjectOne::payloadChanged, &o2, &ObjectTwo::handlePayload);

    QTimer::singleShot(0, &o1, [&] { QMetaObject::invokeMethod(&o1, &ObjectOne::emitPayloadChanged); });

    return app.exec();
}

#include "main.moc"
0

There are 0 answers