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

Reply via email to