Проверка макроса Q_OBJECT с помощью static_assert

У меня есть интересная потребность показать ошибку компиляции, если объявление типа, которое мне было дано, не содержит 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 ответ

Решение

Вот как Qt уже делает это:

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

Обратите внимание, что он использует закрытый 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/

Другие вопросы по тегам