使用 static_assert 检查 Q_OBJECT 宏

Posted

技术标签:

【中文标题】使用 static_assert 检查 Q_OBJECT 宏【英文标题】:Checking Q_OBJECT macro with static_assert 【发布时间】:2014-01-13 21:23:19 【问题描述】:

如果给我的类型声明不包含Q_OBJECT 宏,我有一些有趣的需要显示编译错误。我发现了一种不好的方法。实际上它重复了 Qt 开发人员的想法来做同样的把戏:

template<typename T>
void checkForQObjectMacro()

    reinterpret_cast<T *>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T *>(0));

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

【问题讨论】:

【参考方案1】:

这是how Qt does it already的方式:

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

请注意,它使用的是来自 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) ;
    ;

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

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

【讨论】:

非常感谢,我忘记了我的qt版本已经过时了,好像他们是5.2才做的

以上是关于使用 static_assert 检查 Q_OBJECT 宏的主要内容,如果未能解决你的问题,请参考以下文章

C++11 static_assert关键字

如何将static_assert与sizeof和stringify结合起来?

C ++编译时检查模板类型中是否存在方法

如何用宏做static_assert?

initializer_list::size() 上的 static_assert

MSVC++:模板的 static_assert 不会在 lambda 内触发