QVariant::value<T>() fails to convert unless QVariant::fromValue<T>() has been called previously. Is this expected behaviour?
Asked Answered
M

0

6

Using Qt 6.2.1 with Microsoft MSVC 2019 under Windows.

Given this function to load a list of unsigned ints from persistent settings:

QList<uint> get(QSettings& settings, QString& key) {
    QVariant v {settings.value(key)}
    return v.value<QList<uint>>();
}

The call to v.value() will sometimes fail to convert the value stored in the QVariant, producing this debug message:

QVariant::load: unknown user type with name QList<uint>

The inverse function to store a list always works fine:

void set(QSettings& settings, QString& key, QList<uint> list) {
    QVariant v {QVariant::fromValue<QList<uint>>(list)};
    settings.setValue(key, v);
}

After some debugging, I narrowed down the situations in which the first function fails. It seems it has to do with the registered metatype for the type QList<uint> and its registered data stream operators.

If during the execution of the program the following code has been executed at least once at any point before calling get(), the problematic QVariant conversion will complete without error:

// Either this one
QVariant::fromValue<QList<uint>>(list);
// or these
auto mt = QMetaType::fromType<QList<uint>>();
mt.hasRegisteredDataStreamOperators();

Is this by design or a bug in Qt 6?

This asymmetric behaviour between QVariant::value and QVariant::fromValue is puzzling.

For now, I am getting around the issue by adding dummy calls to force MetaType registration or whatever is going on in the background:

QVariant::fromValue<QList<uint>>(QList<uint>{}); // Dummy call
return v.value<QList<uint>>();

but this feels like a bad hack. If this is not a bug, there surely is a better way. Can anyone shed some light on this matter?

Note qRegisterMetaTypeStreamOperators("name") has been removed in Qt 6.

PS: The example code above is a very simplified version of the real code I am working on.

Millwork answered 3/2, 2022 at 15:55 Comment(4)
Have you found a solution for this problem?Percentile
On the latest Qt version I'm still having the same issue. At least, the dummy call workaround still works fine. You only need to execute those dummy calls once during the execution of the program. That's enough to get your types working.Millwork
Still seem to be an issue on QT 6.5. For me it was a Variant of the type QList<QPointF> and the mentioned workaround still seem to work.Ashelyashen
I see this asymmetric issue on QT 6.7, but calling qRegisterMetaType<Class>() in a constructor resolves this for me.Chalfant

© 2022 - 2024 — McMap. All rights reserved.