简体   繁体   中英

Convert enums in QVariant into integers

I write a library which uses Qt's meta type system. The user of my library can provide values of custom types which get wrapped in a QVariant. Later in some code internally in the library, I need to serialise this QVariant. I implemented serializers for a couple of types and I really don't need to support every type known to the Qt meta type system. I serialise the values in order to send them over the network using JSON.

But what I'd like to achieve is to support custom enum types, which the user has to register to the meta type system using qtRegisterMetaType<MyEnum>("MyEnum"); anyway. I want to serialise such an enum via converting it to an integer type.

I tried QVariant::value<int>() on such an enum value, but it always returns 0. QVariant::canConvert<int>() returns false.

Is it possible (maybe using some dirty hacking) to get to the integer value of the wrapped enum? How does Qt handle enum values in its meta type system? Maybe I can just access the raw void* pointer when I'm sure that this is an enum value I have here.

This leads us to the next question: How to check if a Qt meta type is a user enum type at all?

Please note that since I'm writing internal code of the library, I can't use templates. The only "thing" I have is the QVariant, no compile-time type information.

// 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!

I know that the C++ compiler can choose to use any integer type (not only 32-bit ones) internally to store enum values. Can this be a problem for me? (If I reinterpret the void* as int* for example. But remember that the void* data is allocated by QVariant itself, so it may allocate more than, for example, 2 bytes for a enum with sizeof == 2 .)

A dirty hack would be to serialize the QVariant to a QDataStream, then deserialize the last 4 bytes to an int. This doesn't answer the question of how to check for an enum type. I'll dig deeper into the moc output and update this.

Leemes has helpfully found that QMetaObject::enumerator() will give you all meta enums defined in a class. This is enough for checking if a given type name is an enum or not, as one can convert the enum names to the type IDs using QMetaType::type() (but prepending the class name and "::"). In order to convert from QVariant holding an enum to an int, one simply reinterprets the QVariant::constData() as an int pointer and reads it. It works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM