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

Mutz, Marc marc at kdab.com
Wed May 29 12:53:35 CEST 2019


Hi,

Here's a list of stuff I consider has served it's purpose and is no 
longer needed, with respective replacements:

= Priority 1 =

== QSharedDataPointer / QExplicitlySharedDataPointer ==

These are basically Qt-internals, and should never have been public in 
the first place. It's _because_ they are public that we have two of 
them, and soon a third one (properly non-public): 
https://codereview.qt-project.org/c/qt/qtbase/+/115213 That commit's 
message also explains what's wrong with the QSDP and QESDP.


== Q_FOREACH -> ranged for loops 
(https://codereview.qt-project.org/c/qt/qtbase/+/147363) ==

Q_FOREACH is less readable (because it allows mutating the container 
under iteration), and produces _a lot_ of code. It also is intrinsically 
tied to just a few Qt containers (excluding QVLA). Ranged for loops work 
on anything, incl. a C array. Also, as a macro, it will continue to 
cause problems down the road (e.g. with modules). Being a macro also 
means that it cannot deal with value_types that contain a comma.

=== related: Q_FOREVER -> for(;;) ===

Suggested by Lars in ibid. Basically because it's a macro.


== Java-style iteration 
(https://codereview.qt-project.org/c/qt/qtbase/+/262344) ==

It's very easy to write quadratic loops with it.remove(), and a review 
of Qt code has shown that some users still use container.remove(), which 
is just as unsafe as with STL iterators. I also noted between 100b/loop 
and 5KiB for four loops of text size savings.


== QScopedPointer -> std::unique_ptr ==

Suggested by Thiago on 
https://codereview.qt-project.org/c/qt/qtbase/+/261553

I agree. We now have std::unique_ptr, and it's movable. QScopedPointer 
had the problem that it didn't know what it wanted to be: 
boost::scoped_ptr or std::unique_ptr. A real scoped pointer would not 
offer release(), a unique_ptr would need to provide move semantics. 
QScopedPointer has release(), but no moves (were proposed, but not 
accepted).


== QLinkedList -> std::list 
(https://codereview.qt-project.org/c/qt/qtbase/+/261421) ==

Of the Qt containers, this one is the most-unused (in Qt code), as well 
as the one that's furthest behind it's STL counter-part. Whenever I use 
std::list, I use it for splice(), a function that just cannot be added 
to a CoW container. Qt is already almost completely QLinkedList-free. 
Let's bury QLinkedList.


== qHash() -> std::hash ==

Suggested by Lars in 
https://codereview.qt-project.org/c/qt/qtbase/+/261819. To be precise, 
he's suggesting to specialise std::hash and have qHash() call std::hash.

Only problem I see so far is that std doesn't provide us with a tool to 
hash composites. E.g. there's no std::hash for std::tuple (which would 
mean we can std::tie the members and hash the result), and only C++17 
adds some kind of raw bits hashing (via std::string_view). We'd need to 
provide these building blocks ourselves, which can be done, but it means 
we'll have at least _some_ qHash()-like functions we need for 
std::hash<> implementations.

Actual problem?


== QPaintDevice ==

I'd like this to become a static interface. In very shortened terms: 
everything that has a QPaintEngine *paintEngine() method is a paint 
device. QPainter's ctor would become a template and do the virtual 
dispatch internally, just like Sean Parent's document type in C++ 
Seasoning.

This would solve a lot of problems: QWidget would no longer need to use 
multiple inheritance, and QImage and QPixmap would become proper value 
types, without virtual functions that create problems with move 
semantics and swapping.


== QRegExp ==

Is QRegularExpression good enough these days? :)


== MT plumbing ==

Let's make use of the std facilities to enable checkers such as TSAN to 
work without hacks. It's not Qt's business to reimplement threading 
primitives.

Probably need to keep some stuff around, like QThread, because of the 
interaction with event processing, but before we add a lot of time 
making the following classes play nice with the std, let's perspectively 
remove them:

=== QAtomic -> std::atomic ===

It already is just a thin wrapper around std::atomic, so there's not 
much point keeping it.

=== QMutex / QReadWriteLock -> std::*mutex* ===

It has too many responsibilities. Where the std knows many different 
mutex classes, Qt folds everything into just two.

We probably need to keep QRWL around a while longer, since C++ added 
shared_mutex only in C++17.

=== QMutexLocker -> std::unique_lock ===

1:1 replacement in the vast majority of cases. unique_lock has a lot 
more features (movable, adopting a locked mutex, not tied to any 
particular mutex class, ...)

=== QWaitCondition -> std::condition_variable(_any) ===

Plumbing that std::condition_variable can do better.





= Priority 2 =

== QQueue / QStack -> std::queue, std::stack ==

These classes publicly inherit QList and QVector, resp., and are both 
very inflexible (due to the fixed underlying container), as well as too 
flexible (they offer non-queue, non-stack behaviour, such as iteration).

For QQueue, we have the additional problem that QList is going to be 
deprecated/removed in Qt 6 (see previous discussion).


== QSharedPointer / QWeakPointer -> std::shared_ptr/weak_ptr ==

Once they are stripped of their magic QObject handling and QObject 
handling returned to QPointer proper, they don't do much other than 
std::shared_ptr, except being less flexible and largely untested for 
exception-safety.





= Priority 3 =

== QSet / QHash -> std::unordered_set/map ==

I'd really like to see these gone. Mainly to free up their names for OA 
hash containers, something that the STL doesn't, yet, have.


== QMap -> std::map ==

These classes have taken some design decisions that make them very badly 
integrated into modern C++. One is that QMultiMap is-a QMap. The first 
and foremost is, though, that *it returns value_type, making ranged-for 
useless for maps. If we're going to change the return value of *it, 
though, we might as well kick the whole class out, too, since the code 
adjustments on the user's parts would be roughly the same.


... to be continued.

Flame away :)

Thanks,
Marc


More information about the Development mailing list