c++qtsignals-slotsqmetaobject

Is it possible to have a macro function as a QMetaMethod tag?


Qt allows you to have arbitrary tags on slots/Q_INVOKABLE methods using this syntax:

// In the class MainWindow declaration
#ifndef Q_MOC_RUN
// define the tag text as empty, so the compiler doesn't see it
#  define MY_CUSTOM_TAG
#endif
...
private slots:
    MY_CUSTOM_TAG void testFunc();

I want to make a tag that's a macro function, like this:

#ifndef Q_MOC_RUN
#  define MY_CUSTOM_TAG(...)
#endif
...
private slots:
    MY_CUSTOM_TAG(someData) void testFunc();

Which I hoped would end up as a string in tag() like MY_CUSTOM_TAG(someData) which my code would parse - however, MOC gives me this error:

error: Parse error at ")"

Is there a way to make this work? Or does MOC only support simple macros for tags?


Solution

  • The tl;dr is that you can do this, but moc is picky about what it accepts.

    According to the doc you linked, moc in Qt 5.0+ will expand preprocessor macros. You can confirm this through the following example:

    #ifndef Q_MOC_RUN
        #define MY_TAG(...)
    #else
        #define MY_TAG(x) x
    #endif
    
    class Test : public QObject
    {
        Q_OBJECT
    public:
        explicit Test(QObject *parent = 0);
    
    public slots:
        MY_TAG(qt) void test();
    };
    

    If you inspect the moc-generated moc_test.cpp, you should find 'qt' within the generated string table.

    static const qt_meta_stringdata_Test_t qt_meta_stringdata_Test = {
        {
    QT_MOC_LITERAL(0, 0, 4), // "Test"
    QT_MOC_LITERAL(1, 5, 4), // "test"
    QT_MOC_LITERAL(2, 10, 2) // "qt"
    
        },
        "Test\0test\0qt"
    };
    

    You can also test for success using QMetaMethod::tag() as described in the linked documentation.

    I tested several other macros, and found moc to be rigid in what its accepts. For instance, macros with multiple arguments, and macro bodies including parentheses or dashes resulted in error. moc uses its own preprocessor implementation, and it may be limited compared to the GNU C preprocessor.