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: