Search code examples
c++qtc++11qobjectstatic-assert

Checking Q_OBJECT macro with static_assert


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:

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.


Solution

  • This is the way 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");
    

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

    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:

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