Qt - проверка во время компиляции, был ли вызван qRegisterMetaType <T>() - PullRequest
1 голос
/ 17 апреля 2020


Вопрос: Есть ли способ проверить во время компиляции, был ли вызван qRegisterMetaType<T>() для пользовательского типа T?


Пользовательский тип T должен быть зарегистрирован в системе мета-типов Qt для использования, например, в соединениях с очередями.

Если такое соединение установлено и сработал сигнал, будет показано предупреждение времени выполнения:

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

Это сложно отследить, поэтому я бы предпочел проверить это во время компиляции. Это каким-либо образом возможно?

(я понимаю, что, если бы это было возможно, оно, вероятно, уже было бы частью самой Qt Framework, но, возможно, ...?)


Примечание: я знаю, что могу проверить если тип был объявлен как метатип ( Проверьте, объявлен ли тип как система мета-типов (для SFINAE) ), но это не решает мою проблему.


Пример кода:

#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"
...