Есть ли способ использовать QMetaEnum с Q_ENUMS, принадлежащим не классу Q_OBJECT или Q_GADGET?

Например, у меня есть следующий класс:

namespace someName
{
    class someClass
    {
        Q_ENUMS(ESomeEnum)

        public:
        enum ESomeEnum {ENUM_A, ENUM_B, ENUM_C};

        // ... some other things ..
    }
}

Q_DECLARE_METATYPE(someName::someClass)

Есть ли способ использовать QMetaEnum::valueToKey или QMetaEnum::keyToValue?

Попробовал метод в этом ответе, но получил следующую ошибку:

error: static assertion failed: QMetaEnum::fromType only works with enums declared as Q_ENUM or Q_FLAG
#define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(Condition), Message)

Я могу использовать X-Macros для получения желаемого результата, но было бы неплохо узнать больше трюков в Qt.

2 ответа

Решение

Нет, потому что нет Q_ENUMФункциональность реализована в коде, сгенерированном moc, и moc игнорирует классы, которые не являются Q_OBJECT ни Q_GADGET, Там нет причин, чтобы не использовать Q_GADGET поскольку он не влияет на размер объекта: не добавляет ни виртуальных методов, ни полей данных.

Следующее демонстрирует это:

#include <QtCore>

namespace Ns {
class Class {
   Q_GADGET
public:
   enum ESomeEnum {ENUM_A, ENUM_B, ENUM_C};
   Q_ENUM(ESomeEnum)
};
}

int main() {
   auto metaEnum = QMetaEnum::fromType<Ns::Class::ESomeEnum>();
   qDebug() << sizeof(Ns::Class) << metaEnum.valueToKey(Ns::Class::ENUM_A);
}
#include "main.moc"

Выход:

1 ENUM_A

На этой конкретной платформе (и многих других) пустые классы имеют размер 1.

Да, с 5.8 вы можете сделать:

namespace MyLibrary
{ 
Q_NAMESPACE 

enum class MYLIBRARYSHARED_EXPORT MyEnumClass
{
...
}; 

Q_ENUM_NS(MyEnumClass)

...
} // namespace MyLibrary

Q_ENUM как старый Q_ENUMS но с этими различиями:

  • Это должно быть размещено после enum в исходном коде.
  • Только один enum можно положить в макрос.
  • Это позволяет QMetaEnum::fromType<T>(),
  • Эти enums автоматически объявляются как QMetaTypes (нет необходимости добавлять их в Q_DECLARE_METATYPE больше).
  • enumс переданы qDebug напечатает имя значения, а не число.
  • Когда положить в QVariant, toString() дает имя значения. Имя значения напечатано QCOMPARE (начиная с Qt 5.6)

Взято из блога WOBOQ по теме, прочитайте его для получения дополнительной информации относительно Q_ENUM против Q_ENUMS,

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