[Development] QOptional

Marc Mutz marc.mutz at kdab.com
Wed Aug 20 20:49:03 CEST 2014


On Wednesday 20 August 2014 20:04:24 Иван Комиссаров wrote:
> First is a QVariant integration. I think, i should add:
> 1) template<typename T> QVariant::QVariant(const QOptional<T> &o);
> constructor

static fromOptionalValue()
(like fromValue())

Please don't add a templated ctor to QVariant. It currently doesn't have one, 
and if you add that ctor, as implicit even, you may change the meaning of this 
code:

    QVariant v(t);

where t, say, has an implicit conversion to int. The call might become 
ambiguous.

Also, QVariant v = t; for any currently supported type decltype(t) means that 
v _contains_ a t. In particular, if QVariant v = t compiles, then it is equal 
(in type and content) to fromValue(t). With your proposal that's no longer 
true. If t is a QOptional<T>, v would now contain a T, which is different from 
decltype(t).

> 2) template<typename T> QOptional<T> QVariant::toOptional()
> const; method (like value<T>())

toOptional_Value_() (to mimick value<T>().
 
> Right now, QOptional has isNull() method that indicates that optional
> object has no value. I suggest to rename this method to isValid() and add
> new isNull() method that checks if optional contains default-constructed
> value. This will make it more consistent with QVariant API.

What QOptional should be consistent with is a T*, and std::optional, because 
that's what it's replacing. Qt smart pointers have isNull(). Just mention the 
simile in the docs, and no-one will look for isNull(). IIRC, std::optional 
uses something way more esoteric, like is_engaged() or so (I'm not proposing 
that).

With isValid() you will have the same problem. If isNull() checks !opt || 
opt.value().isNull(), then it's hard to argue why isValid() shouĺd check 
anything but opt && opt.value().isValid().

I don't find the QVariant::isNull behaviour any useful or intuitive. It's too 
smart. You can always use v.value<T>().isNull() because value() will return a 
default-constructed T if invalid.

> So, the i vote for following behaviour;
> Invalid QVariant (no type) <-> invalid QOptional of type T
> null QVariant (QString) <-> valid QOptional containing QString()
> non-null QVariant containig QString("") <-> valid QOptional containing
> QString("") non-null QVariant containing non-empty string <-> valid
> QOptional containing non-empty string
> 
> Second, i would like to hear some expertise about current implementation
> using "aligned" storage. Will it work? More, this implementation has a
> problem - QOptional(T) constructor can't be marked constexpr (as it uses
> placement new), which makes class useless for constant expressions at all.
> Should i add also c++11 implementation based on unions?

In C++11 generalized unions you still have to use placement new to intialize 
non-POD members, iirc.

While it would be nice if the QOptional(T) ctor would be constexpr, I don't 
think that's a strong requirement. QOptional() and many other 

>  (what would happen
> if we use c++98 compiled Qt with c++11 compiled app?)

As long as the struct are layout-compatible, probably nothing. I don't know of 
the top of my head, however, whether C++ defines the memory layout of unions 
with members of different size, though the only sane definition would be that 
all members have the same address.

Thanks,
Marc

-- 
Qt Developer Days 2014 - October 6 - 8 at BCC, Berlin

Marc Mutz <marc.mutz at kdab.com> | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
www.kdab.com || Germany +49-30-521325470 || Sweden (HQ) +46-563-540090
KDAB - Qt Experts - Platform-Independent Software Solutions



More information about the Development mailing list