[Development] Use QMetaEnum::keyCount() to initialise array

Tom Isaacson Tom.Isaacson at navico.com
Sun Dec 30 20:43:21 CET 2018


Is it possible to use QMetaEnum::keyCount() to initialise an array? Something like:

    const QMetaEnum metaEnum = QMetaEnum::fromType<MyArray>();
    int MyArray[metaEnum.keyCount()];

After asking this on the Qt-Interest forum I spent a bit of time investigating. Q_ENUM declares functions with Q_DECL_CONSTEXPR:
    #define Q_ENUM(ENUM) \
        friend Q_DECL_CONSTEXPR const QMetaObject *qt_getEnumMetaObject(ENUM) Q_DECL_NOEXCEPT { return &staticMetaObject; } \
        friend Q_DECL_CONSTEXPR const char *qt_getEnumName(ENUM) Q_DECL_NOEXCEPT { return #ENUM; }

In my example code above, QMetaEnum::fromType() calls these functions:
    template<typename T> static QMetaEnum fromType() {
        Q_STATIC_ASSERT_X(QtPrivate::IsQEnumHelper<T>::Value,
                          "QMetaEnum::fromType only works with enums declared as Q_ENUM or Q_FLAG");
        const QMetaObject *metaObject = qt_getEnumMetaObject(T());
        const char *name = qt_getEnumName(T());
        return metaObject->enumerator(metaObject->indexOfEnumerator(name));
    }

Where it breaks is the last line, because QMetaObject::indexOfEnumerator() uses d.data:
https://github.com/qt/qtbase/blob/96efc38f100686a8183f45367e54bf6cb670bdba/src/corelib/kernel/qmetaobject.cpp#L968
    int QMetaObject::indexOfEnumerator(const char *name) const
    {
        const QMetaObject *m = this;
        while (m) {
            const QMetaObjectPrivate *d = priv(m->d.data);

Which is only defined as const:
https://github.com/qt/qtbase/blob/96efc38f100686a8183f45367e54bf6cb670bdba/src/corelib/kernel/qobjectdefs.h#L578
    struct { // private data
        const QMetaObject *superdata;
        const QByteArrayData *stringdata;
        const uint *data;

I don't know how the Meta-Object Compiler creates this but surely it's possible to change it to be constexpr?

Tom Isaacson




More information about the Development mailing list