[Development] RFC: QVariant changes in Qt6

Olivier Goffart olivier at woboq.com
Sun Nov 24 22:02:32 CET 2019

On 24.11.19 21:53, Mathias Hasselmann wrote:
> OMG, are you really sure about these massive changes?

Not 100% sure, no.
What specific changes are you worried about?
In this case, I believe the changes should lead to only small behavior changes 
which are in fact fixes.
But this is of course up to discussion.
As always, it is a trade-of between stability but stagnation, or evolution.

> I am pretty sure that this will introduce countless hard to catch porting 
> issues. After all there are no compiler warnings for this, only subtile 
> behavior changes and I doubt that all the Qt based projects out there have 
> sufficient test coverage to catching automatically.
> What are your plans to support Qt users to catch these behavior changes?
> Ciao
> Mathias
> Am 22.11.2019 um 14:32 schrieb Olivier Goffart:
>> Hi,
>> This is a follow-up on what was discussed in the (second part of the) QtCore 
>> session in the QtCS.
>> Lars and others have been mentioning that they dislike implicit conversions 
>> within QVariant. Creating a new class (QAny) has been suggested, that would 
>> be like QVariant but without the conversions.
>> I am personally not in favor of this change because we are using QVariant all 
>> over the place in our API and so we cannot really deprecate QVariant. It will 
>> cause much confusion to user to have two similar classes. And the difference 
>> is not big enough to force a new class.
>> So here is what I suggest we do in Qt6. None of this is implemented yet, it 
>> is only proposed on this list for feedback.
>> 1. operator==
>> In Qt6, QVariant::operator==() will no longer do any conversions.
>> If two QVariant does not have exactly the same, they will no longer be 
>> considered equal.
>> Also, in Qt6, QMetatype will gain ability to register the operator==, and 
>> therefore it will work for any type (and not only for builtin type as 
>> currently).
>> So right now,
>>    QVariant(QByteArray("Hello")) == QVariant(QString("Hello"))
>> is true, but in Qt6 it will be false.
>> This is a behavior change, but I believe this is something we can afford to do.
>> I do not have data on how much code will break with this change, but i feel 
>> most use of operator== are there for optimisations: i.e: setFoo(const 
>> QVariant &foo) { if (m_foo == foo) return; ... }
>> Maybe we'll have more data once we actually implement the change and see if 
>> too many things breaks.
>> 2. operator< and other comparison operator
>> Deprecate in Qt 5.15, remove in Qt 6
>> It is not possible to implement it correctly with a total order.
>> I could not find direct use of the operator in the code indexed on 
>> https://code.woboq.org/qt5 (only in QmlDesigner::operator< which is itself 
>> not used)
>> Sorting on variant does not really make sense. Even code that does, like 
>> QAbstractItemModelPrivate::isVariantLessThan does not use operator<.
>> Where this is used may be the use of QVariant as a key in a QMap. This is 
>> problematic because the operator< does not implement a total order, so you 
>> can have funny results.
>> I could not find instances of that in Qt or QtCreator, but Github search for 
>> "QMap<QVariant," shows many result :-(
>> I'd still want to deprecate it. User could wrap QVariant in their own 
>> MySortedVariant with their own operators that does what they need for their 
>> use case.
>> 3. conversions in QVariant::value
>> We would like to avoid having automatic conversion in QVariant::value.
>> So Qt6 would be
>>    std::optional<T> QVariant::value() const;
>> And we could deprecate the current one in Qt5.15 in favor of qvariant_cast 
>> which is explicit.
>> This one is a bit more controversial maybe. Because there are thousands of 
>> call to QVariant::value all over the place. But "value()" is the ideal name 
>> for the non-converting variant.
>> A clazy script to replace QVariant::value with qvariant_cast will be in order.
>> 4. All the implicit constructors for builtin types.
>> QVariant has many implicit constructors for all the builtin types.
>> I suggest to replace them all with a template<typename T> QVariant(T&&) 
>> constructor. (same as std::any.) So builtin types are no longer special.
>> 5. All the method toXxx (where Xxx is a builtin type)
>> Leave them as-is?
>> However some of them are for types that may go outside of QtCore, these 
>> should be deprecated in Qt 5.15 and removed in Qt6
>> 6. QVariant::Type and QMetaType::Type enums
>> QVariant::Type is already marked as obsolete in the documentation, but not 
>> yet marked as deprecated.
>> So we can remove it in Qt6, and we should try to mark it as deprecated in Qt 
>> 5.15. But that's hard because it is used all over the place.
>> QMetaType::Type will be marked as deprecated in Qt6, but i'm afraid we cannot 
>> simply remove it.
>> In  general, all the integer id API for QMetaType will be deprecated in Qt6, 
>> one should use QMetaType by value. The integer id will stay in Qt6. This 
>> means that there will still be a central registry of types but it would only 
>> be there for the types for which we ask the id (and for the builtin types)
> _______________________________________________
> Development mailing list
> Development at qt-project.org
> https://lists.qt-project.org/listinfo/development

More information about the Development mailing list