将QVariant中的枚举转换为整数

3
我编写了一个使用Qt元类型系统的库。我的库的用户可以提供自定义类型的值,这些值被包装在QVariant中。稍后,在库的某些内部代码中,我需要序列化此QVariant。我为一些类型实现了序列化器,而我确实不需要支持Qt元类型系统中已知的每种类型。我将值序列化以便使用JSON通过网络发送它们。
但是我想要实现的是支持自定义枚举类型,用户必须使用qtRegisterMetaType<MyEnum>("MyEnum");将其注册到元类型系统中。我希望通过将其转换为整数类型来序列化这样的枚举。
我尝试对这样的枚举值使用QVariant::value<int>(),但它总是返回0。QVariant::canConvert<int>()返回false。 有可能(也许使用一些肮脏的技巧)获得包装枚举的整数值吗? Qt如何处理其元类型系统中的枚举值?也许我只需在此处访问原始void*指针当我确定这是我拥有的枚举值时。
这引出了下一个问题:如何检查Qt元类型是否根本是用户枚举类型? 请注意,由于我正在编写库的内部代码,因此无法使用模板。我拥有的唯一“东西”是QVariant,没有编译时类型信息。
// code in the project using my library:
MyEnum foo;
libraryFunction(foo);

// internal library code (note that compile-time type info isn't available):
QVariant foo = getValueAsVariant(...);
if (/* how to check if foo is an enum type? */)
    int enumValue = foo.value<int>(); // not working for enums!

我知道C++编译器可以选择任何整数类型(不仅限于32位)来内部存储枚举值。这会对我造成问题吗?(例如,如果我将void*重新解释为int*。但请记住,void*数据是由QVariant本身分配的,因此它可能为sizeof == 2的枚举类型分配超过2个字节的空间。)

1个回答

4
一个简单的处理方法是将QVariant序列化为QDataStream,然后将最后4个字节反序列化为int。这并不能回答如何检查枚举类型的问题。我将深入挖掘moc输出,并更新此内容。
Leemes很好地发现了QMetaObject::enumerator(),它会给出类中定义的所有元枚举。这已经足够检查给定类型名是否为枚举类型了,因为可以使用QMetaType::type()将枚举名称转换为类型ID(但要在类名和“::”之间加上前缀)。为了将包含枚举类型的QVariant转换为int,只需将QVariant::constData()重新解释为int指针并读取即可。它能正常工作。

谢谢。到目前为止,我发现有关 moc 输出的信息如下:在头文件中使用 Q_ENUMS(MyEnum) 后,moc 会为每个枚举类型在字符串数据中生成条目。它包含枚举名称和所有条目及其名称。看起来很不错。但我不知道如何从外部访问这个字符串数据。更新:当然,这只对成员枚举有效,而全局作用域中的枚举则不行。但是我可以很好地遵守这个限制。我的库已经了解了可能包含元枚举的每个 QMetaObject。扫描它们就足够了。 - leemes
我所说的“成员枚举”是指在类内定义的枚举。这个术语是错误的。 - leemes
好的,我知道了。 QMetaObject :: enumerator()将为我提供在类中定义的所有元枚举。 这已足以检查给定类型名称是否是枚举类型,因为我可以使用QMetaType :: type()将枚举名称转换为类型ID(但要在类名和“::”前缀)。 为了从包含枚举的QVariant转换为int,我只需重新解释QVariant :: constData()作为int指针并读取它。 它有效。 但是,如果您在“深入挖掘 moc 输出”时发现更多信息,请告诉我。 我接受您的答案,因为它向我展示了正确的方法 ;) 谢谢! - leemes
1
很高兴我能提供一点帮助 :) 我真的很想念 QMetaObject::enumerator() 成员!谢谢,我想你也帮了我一个大忙! - Kuba hasn't forgotten Monica
1
很高兴我也能帮到你 :) 或许你想把这个加入到你的答案中,以便帮助其他人阅读它? - leemes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接