使用static_assert检查Q_OBJECT宏。

时间:2022-03-14 18:46:11

I have some interesting need in showing a compilation error if the declaration of the type I was given doesn't contain the Q_OBJECT macro. I found one bad way to do it. Actually it repeats the idea of Qt developers to do the same trick:

如果给定的类型声明不包含Q_OBJECT宏,那么在显示编译错误时,我有一些有趣的需求。我发现了一个不好的方法。实际上,它重复了Qt开发人员的想法:

template<typename T>
void checkForQObjectMacro()
{
    reinterpret_cast<T *>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T *>(0));
}

This works well but it gives indeed strange error message. I want to show a readable message. One way to do this is using static_assert construction. But I have no idea how to implement statically verified condition of Q_OBJECT macro presence. Maybe someone can propose a beautiful hack? Also any idea is greatly appreciated.

这很有效,但它给出了一个奇怪的错误消息。我想显示一个可读的消息。一种方法是使用static_assert构造。但是我不知道如何实现Q_OBJECT宏存在的静态验证条件。也许有人可以提出一个漂亮的hack?也非常感谢您的任何想法。

1 个解决方案

#1


3  

This is the way how Qt does it already:

这就是Qt的方法:

Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
"No Q_OBJECT in the class with the signal");

Note that it is using a private API though from here:

请注意,它使用的是一个私有API:

namespace QtPrivate {
    /* Trait that tells is a the Object has a Q_OBJECT macro */
    template <typename Object> struct HasQ_OBJECT_Macro {
        template <typename T>
        static char test(int (T::*)(QMetaObject::Call, int, void **));
        static int test(int (Object::*)(QMetaObject::Call, int, void **));
        enum { Value = sizeof(test(&Object::qt_metacall)) == sizeof(int) };
    };
}

Here you can see the change on Gerrit that landed in 5.2:

在这里你可以看到Gerrit的变化在5.2:

https://codereview.qt-project.org/#change,65508

https://codereview.qt-project.org/的变化,65508年

#1


3  

This is the way how Qt does it already:

这就是Qt的方法:

Q_STATIC_ASSERT_X(QtPrivate::HasQ_OBJECT_Macro<typename SignalType::Object>::Value,
"No Q_OBJECT in the class with the signal");

Note that it is using a private API though from here:

请注意,它使用的是一个私有API:

namespace QtPrivate {
    /* Trait that tells is a the Object has a Q_OBJECT macro */
    template <typename Object> struct HasQ_OBJECT_Macro {
        template <typename T>
        static char test(int (T::*)(QMetaObject::Call, int, void **));
        static int test(int (Object::*)(QMetaObject::Call, int, void **));
        enum { Value = sizeof(test(&Object::qt_metacall)) == sizeof(int) };
    };
}

Here you can see the change on Gerrit that landed in 5.2:

在这里你可以看到Gerrit的变化在5.2:

https://codereview.qt-project.org/#change,65508

https://codereview.qt-project.org/的变化,65508年