Digging up this conversation cause I believe it would be a big added value, or at least make it should be made clear if that's not possible.
Le ven. 21 juil. 2023 à 11:37, Giuseppe D'Angelo via Development < development@qt-project.org> a écrit : > On 21/07/2023 11:01, Volker Hilsheimer via Development wrote: > > How about conversion: > > I, for one, would like to stop seeing magic conversions added into > QVariant, and keep breaking stuff at every Qt major release because we > realize we went overboard and have to remove features. I agree that we should keep the conversions to a minimum. std::optional<int> opt; // nullopt > QVariant v = QVariant::fromValue(opt); > > Is `v` a null QVariant with Int metatype, or a valid variant with a > std::optional<int> metatype loaded with a copy of the optional? What if > `opt` is loaded instead? > Keeping a copy of the std::optional<int> (nullopt or containing an int) seems like the sensible choice here, no magic conversions. So this at a minimum is a different named constructor: > QVariant::fromStdOptional or similar. This doesn't help at all in > generic code (e.g. in the property system) -- when is one supposed to > unwrap an optional vs keep it wrapped? > Do we need that constructor if we always keep the optional wrapped? As you said we can already construct a QVariant from a std::optional. > QVariant(42).value<std::optional<int>>(); // std::optional holding 42 > > No, returns nullopt, types don't match and not in the list of magical > conversions > Does that mean the following couldn't be done? Or could the magic be kept only in the QML conversion layer? In c++: Q_PROPERTY(std::optional<int> boundary READ ... WRITE ... NOTIFY ...) In QML: property int effectifyBoundary: Backend.boundary ?? 0 // Backend.boundary being undefined if it's a nullopt or converted to an int if it has a value. Backend.boundary = slider.value // slider.value being an int and the WRITE method receiving a std::optional<int> with its value; Backend.boundary = undefined // WRITE method receiving a nullopt What might be harder is doing that with models and delegates, setData just has a QVariant for the value. One might assume that if undefined is passed to the method it would be a invalid QVariant. Typing it I realize it might not be such a problem though, doing the following manually is acceptable: std::optional<int> optionalValue; bool ok; int value = variant.toInt(&ok) if (ok) { optionalValue = value; } Maybe that could be done with a new helper : std::optional<int> optionalValue = variant.optional_value<int>() // working with int metatype, invalid metatype and std::optional<int> metatype. An issue that might arise is some generic models just transfer setData to some object->setProperty (example : https://github.com/OlivierLDff/ObjectListModel/blob/master/src/include/ObjectListModel/ObjectList.hpp#L208 ) Should writing an int QVariant or an invalid QVariant to a std::optional<int> be supported? If not, some way to construct a std::optional<Foo> QVariant from a Foo QVariant or Invalid QVariant should be provided (convert_to_optional maybe?). And a way to access the underlying value metatype too maybe. Basically the above can be resumed to the following: With the constraints of not adding magical conversions, can we do something to add std::optional support to the C++/QML interrop? Or is that a big nono for now, waiting for Qt 7 or never to see the light of the day? I believe adding more strongly typed stuff like that is the way forward to have better declarative APIs in QML, I hope it is possible to do. Cheers, Pierre-Yves Siret
-- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development