【问题标题】:Is there a way to use QMetaEnum with Q_ENUMS belonging to non Q_OBJECT or Q_GADGET class?有没有办法将 QMetaEnum 与属于非 Q_OBJECT 或 Q_GADGET 类的 Q_ENUMS 一起使用?
【发布时间】:2026-02-11 02:55:01
【问题描述】:

例如我有以下课程:

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 ?

尝试this answer中的方法却报错:

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 中学习更多技巧也很好。

【问题讨论】:

  • 您使用的是Q_ENUMS,我认为在这种情况下您必须使用Q_ENUM
  • 我正在维护以这种方式编写的代码,将 Q_ENUMS 更改为 Q_ENUM 会向项目经理标记不必要的“恐慌”,因为这会影响很多文件。
  • 到目前为止,接受的答案应该不同。 @DrumM 是正确的,因为 Qt 5.8 你可以使用 Q_NAMESPACE + Q_ENUM_NS 组合。

标签: c++ qt qmetaobject


【解决方案1】:

不,没有,因为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。

【讨论】:

    【解决方案2】:

    Q_ENUM 与旧的 Q_ENUMS 类似,但有以下不同:

    • 需要放在源代码中enum之后。
    • 只能在宏中放入一个enum
    • 它启用QMetaEnum::fromType&lt;T&gt;()
    • 这些enums 会自动声明为QMetaTypes(无需 将它们添加到 Q_DECLARE_METATYPE 中)。
    • enums 传递给 qDebug 将打印值的名称而不是 号码。
    • 当放入QVariant 时,toString() 给出值名称。值名称 由QCOMPARE 打印(自 Qt 5.6 起)

    取自WOBOQ blog post on the topic,阅读它以获取有关Q_ENUMQ_ENUMS 的更多信息。

    【讨论】:

      【解决方案3】:

      是的,从 5.8 开始你可以这样做:

      namespace MyLibrary
      { 
      Q_NAMESPACE 
      
      enum class MYLIBRARYSHARED_EXPORT MyEnumClass
      {
      ...
      }; 
      
      Q_ENUM_NS(MyEnumClass)
      
      ...
      } // namespace MyLibrary
      

      【讨论】:

        最近更新 更多