[Development] Qt 5 types under consideration for deprecation / removal in Qt 6

Kevin Kofler kevin.kofler at chello.at
Wed Jun 5 00:39:22 CEST 2019

Mutz, Marc via Development wrote:
> I'd still like to deprecate them. QSDP is issuing atomic operations on
> each mutable access hurting code-gen,

Well yes, you have to use constData() or cast to const where needed. That
does not reduce QSharedDataPointer's usefulness. It is an implementation
tool for people who know what they are doing.

> and produces surprises such as
> https://codereview.qt-project.org/gitweb?p=qt%2Fqtbase.git;a=commit;h=96dc9a19ae11ca140d681f0e2605b5f4b953e581

My existing QSharedDataPointer code always checks truth with
if (d.constData()) and never if (d).

> or
> https://codereview.qt-project.org/gitweb?p=qt%2Fqtbase.git;a=commit;h=a2cdfd23d61c8dd3a346982caaf1e846e30513b0

I haven't had a need for this idiom in my code yet, but instead of using
QExplicitlySharedDataPointer, I would have fixed it by adding some casts to
const for the read-only checks (probably with something like:
#define CD ((const QSharedDataPointer<Foo> &)(d))
to cut down on copy&paste).

> or
> https://codereview.qt-project.org/gitweb?p=qt%2Fqtbase.git;a=commit;h=188eea0eb47c499f70a60f573948d529089d93b1.

I'm not sure I understand the issue there. Thanks to the atomic reference
counts, implicitly-shared classes are as thread-safe as plain classes
without the CoW magic. But writing to the same object from 2 threads without
some form of mutex will work in neither case. Just don't do that.

> QESDP has the bug that it doesn't propagate const. We could fix that,
> but it would be SiC, too. So, my idea was to keep them both, deprecate
> them, and use something much more cumbersome to use outside of Qt for
> Qt's own classes. I'd also be ok with keeping a fixed QESDP, but QSDP
> should go sooner rather than later.

No, QSharedDataPointer must not go away, not now…

> That said, I'm ok with keeping them until Qt 7, but deprecated.

… and not in Qt 7 either!

>>> == Java-style iteration
>>> (https://codereview.qt-project.org/c/qt/qtbase/+/262344) ==
> [...]
>> I’m a bit torn here. On code review I gave a +1 on deprecating them,
>> but I see that this could lead to a lot of porting effort on user code
>> that makes extensive use of them. And the problem is that the porting
>> can be non-trivial in cases where the list gets modified while
>> iterating. So I think we should most likely keep them for Qt 6.
> As I wrote in the other thread, I'm ok with keeping them. I'd like to
> deprecate them, though.

Deprecating them means you don't want to keep them permanently though, and I
don't see why. They not only help developers coming from a Java background,
but are also more intuitive for new developers.

Yes, the STL-style iterators are more powerful in some ways, and yes, they
are needed to use STL algorithms on the Qt containers. But nobody is taking
them away from you anyway. It just does not preclude also offering a more
developer-friendly API.

>>> == QLinkedList -> std::list
>>> (https://codereview.qt-project.org/c/qt/qtbase/+/261421) ==
> [...]
>> It’s not used a whole lot, and I’m not against deprecating it. But do
>> we need to remove it for 6.0? Or maybe go the route we thought about
>> for other containers as well and have it wrap a std::list. ie. remove
>> our implementation, keep our API.
> I'd just let it sit in it's place, deprecated, untouched. It's not used
> in any Qt API, and the uses which I found in Qt are questionable to
> begin with.

There too, "just let it sit in it's place, deprecated, untouched" is a
contradiction: if you deprecate it, it is not going to "sit in its place"
forever. But a data structure as common as a linked list should not go away.
(Especially not if the datastructure with the next-fastest random-access
inserts and removals, the array of pointers, is also going away.)

> I'm concerned about their use in APIs. I don't know any other library
> that is passing hash tables around through the API for small things like
> mapping role indexes to role names. That's an array of struct job.

Passing around a map is exactly what a hash table like QHash or a tree map
like QMap are for. I have seen lots of APIs in various programming languages
using them for the purpose they were designed for, and even written some of
them myself (both in C++ with Qt and in other programming languages).

> How do you intend to address the problem that QHash/QMap are all but
> unusable in C++11 ranged for loops, because of decltype(*it)?

Can't we just add a keySet() method (named after the Java one that does
something similar) that returns a wrapper object that just forwards begin()
to the map's keyBegin() etc.? Then you could just write something like:
for (auto key : map.keySet())
and it should do conceptually the same as:
for (auto key : map.keys())
but without ever having to build the list of keys as a list.

Or, probably even more efficiently, add cursorBegin() etc. iterator methods
that return iterators returning key-value pairs as QPair, and a cursorSet()
that returns a wrapper object for them like keySet() above. Then:
for (auto cursor : map.cursorSet())
would get you key-value pairs, wouldn't it?

        Kevin Kofler

More information about the Development mailing list