[Development] QList for Qt 6

Mutz, Marc marc at kdab.com
Thu May 23 13:26:09 CEST 2019

On 2019-05-23 10:40, Lars Knoll wrote:
>>> 4. Use QVector to implement QList<Foo>, if sizeof(Foo) <=
>>> sizeof(quint64) and Foo is movable. I’m intentionally not using
>>> sizeof(void *) here, as types with sizes between 4 and 8 bytes would
>>> not have stable references in cross platform code, so I do not 
>>> believe
>>> lots of code would assume that (or it would have broken on 64 bit).
>> Agreed. This matches what QList currently does, minus the padding, 
>> which is good.
> I tried this, and the problem here is that this requires T to be fully
> declared at the time you instantiate QList<T>. This is a source
> incompatibility for class declarations such as
> class MyClass {
> 	QList<MyForwardDeclaredType> list;
> };
> This worked in Qt 5, but wouldn’t work here anymore as I can’t select
> the implementation of QList for a forward declared class.

I agree we should not break this. The standard has just added similar 
guarantees for it's own containers.

> At the same time, I’m not really willing to compromise on this point,
> as I really want to have a zero copy conversion between QList and
> QVector for small movable types (the most common case).

I don't see why a zero-copy conversion between QList and QVector for 
vector-like QList is needed.

You said that QList should vanish from Qt API. So we don't care. We'll 
have that switch to make QList _be_ QVector for ese of porting, but as a 
template alias. There's your zero-copy conversion :) That leaves users. 
And I repeat: I'd leave QList alone (as QArrayList, possibly with always 
IndirectLayout), and just have implicit deprecated conversions between 
QArrayList and QVector. You shouldn't care about performance of unported 
code: It's easy to target both Qt 5 and Qt 6 if you use auto for 
receiving from Qt API. For sending to Qt API, it's a bit more tricky. 
You need to ifdef or live with the implicit conversion in a Qt 6 build, 
but it's not something that we should optimize for. Really. Don't.

So, I'd try the following:

- have a compile switch that hides QList and replaces it with a template 
alias to QVector. This is BC if you compiled with the switch off. 
Clients using the alias will never see the QList name, so won't use the 
code compiled into QtCore for it. So, no need to make it all-inline.

     #if QList-as-QVector
     template <typename T> using QList = QVector<T>;
     ~~~ QList impl, unchanged, except for implicit deprecated 
conversions to/from QVector added ~~~

- port QtCore away from QList

- flip the switch (in CI) for all other libraries except QtCore (so 
QtCore keeps compiling QList in, for other users)

- deal with the fallout

- once reasonably sure all stability-of-reference users have been ported 
away from QList, do s/QList/QVector/g when convenient and unflip the 
switch in CI

- ok, so keep the switch for final release, buf off (and it never 
affects the QtCore build)

- bonus: rename QList to QArrayList, using IndirectLayout 
unconditionally, and make the name 'QList' a deprecated template alias 
for (depending on compile switch) QArrayList (default) or QVector (for 
the fireworks). I'd go to this length _only_ if we think that QArrayList 
(always IndirectLayout) is a worthwhile container to have (remember, 
there's always vector<unique_ptr>) and thus it's going to be maintained 
going forward. If it's not, I'd leave it as QList and deprecate it.


More information about the Development mailing list