[Development] Proposal: Deprecate QVector in Qt 6
Giuseppe D'Angelo
giuseppe.dangelo at kdab.com
Thu Apr 23 16:45:02 CEST 2020
On 4/23/20 1:20 PM, Edward Welbourne wrote:
> So how much harm does it really cause, to keep both names; and use
> whichever feels like the more natural description of the value one is
> returning ?
I missing the bigger picture about this thread. What are we trying to
assess / solve?
== Source compatibility in the presence of QList = QVector (only
relevant for porting code from Qt 5 to 6)? ==
There are some known breakages [1]. But the example quoted before,
QList<T> fun();
will still work whether the client code uses QList<T> or QVector<T> to
store the result. That's why I was asking what that was about.
Similarly,
QVector<T> fun();
will also allow
QList<T> l = fun();
Can this cause source incompatibilities? How? How would the proposed
QVector = QList change things instead?
== API maintenance if QList = QVector: do we mass s/QList/QVector/g in
our public APIs? ==
I'd be in strong favour of it; it favours consistency and one single
message.
Please: let's not open the debate about whether it's a good idea to have
functions that return containers when such containers are not part of
the object representation (vs: those functions use output iterators, or
become coroutines, etc., so I can choose the container I want). We have
those functions around and we need a source compatible solution for them
in 6.0.
The problem I see with this is the sheer size of the task ahead. I'm not
sure how much it can be automated. Has anyone tried? Even if some magic
script fixes everything we may still need manual style touches.
Does it need a C++ parser, or can it be a mass search&replace?
(And even if could build a clang script that does it for Qt itself, what
about user code which won't compile at all under clang?)
On the positive side, since we're talking about typedefs, this can be
done incrementally, without any API/ABI compatibility concerns.
If we went the other way around, i.e. QList is the "default" type, like
proposed: doesn't the task stay fundamentally the same?
== Naming of functions and types if QList = QVector ==
We have QStringList, QVariantList and friends, which are aliases /
subclasses of QList<QString> and so on.
Should they become QStringVector, QVariantVector; and the *List names
stay, aliases for the *Vector names, mirroring QList and QVector
themselves?
I'd say yes, but this has another impact on the API maintenance (we
should change all of our public APIs to use the *Vector types, for
consistency).
A broader question is: in the long run, do we want start deprecating all
the *List names, and leave just the *Vector names? If yes, then
certainly we have to do the replacements.
As proposed in this thread, if we keep QList and make QVector the alias,
then we would just leave these datatypes unchanged, and there would be
no need of introducing the *Vector counterparts.
Functions naming: how many public APIs have a "List" suffix,
specifically returning a QList? (=> QTextCursor::insertList doesn't count.)
First and foremost, we have a problem of coding guidelines, which demand
simple pluralization of the entity returned, not "List" suffixing:
* QObject::children, not childList
* QObject::dynamicPropertyNames, not dynamicPropertyNameList
* QSslSocket::sslErrors, not sslErrorList
* QRegularExpressionMatch::capturedTexts, not capturedTextList
* QSslConfiguration::supportedEllipticCurves, not
supportedEllipticCurveVector (yes, this one returns a QVector)
So the first "go to" solution is: rename the functions, so they follow
the guideline (keep and deprecate the old name).
Second, would it cause confusion for a function called getFooList() to
return a QVector? Is "list" used as an abstraction of the return type
(it doesn't return an object, but a sequence of them), or strictly in
some sort of Hungarian notation to require that the type returned is a
QList? (And I mean, specifically _spelled_ QList, even if it's an alias
to QVector).
I don't have a good answer here.
== Terminology, "list" vs "vector"? ==
Debating whether "vector" is a good term for the respective container is
only useful for mathematicians and linguists -- in other words, all
aboard the bikeshedding train!
But: *today*, in 2020, in C++, it represents a very specific and
well-understood thing. Same for "list". They should cause no
ambiguities. I cannot stress enough that we shouldn't and cannot
possibly care about the names in other languages!
(Otherwise, "list" in Python is heterogeneous, why isn't QList
heterogeneous? Don't we care about developers coming from Python? Repeat
for any other language out there.)
The major problem in this department has to do with caring that
something is actually a vector (contiguous in memory, etc.) rather than
just a sequence implemented "somehow" (... as efficiently as possible,
this is C++ after all).
In this regard, QList is a bad term for representing a generic sequence
(because "list" already has a meaning in C++).
I'm not proposing a type-erased sequence type. I'm just thinking: when a
function returns a QVector, is it because we care about the
representation? When a function returns a QList, is it because we
_don't_ care about the representation? (Because, well, it's not a list!).
This strongly favours QVector in the sense that it does what it says on
the box, whether you care about its actual representation or not; vs.
QList which says "I'm a list" but somehow implies "you don't care" (and
actually means "I'm a vector")
== Teachability ==
Builds upon terminology, but surely, deserves its own point.
1) It doesn't help that for years we've said "don't use QList, use
QVector"; and now in Qt 6 we do the switcharoo and say "use QList, don't
bother with QVector, it's just an old alias".
It can be managed; "that was about Qt 5 QList, Qt 6 QList is different".
I'm not sure how many people care about it, to be honest.
2) It doesn't help that it's still called "QList". "Why is Qt not using
a vector here?" "It is, in fact, a vector" "Then why it's called QList"
and similar.
3) It doesn't help that 100% of the existing teaching material is still
targeting Qt 5 (and 4). That material uses QList (and QStringList, etc.)
and will be around for a long, long time. Using it to learn Qt 6 might
cause some confusion about what's going on with all the *Vector types
instead. I still think it can be managed, though.
4) It helps having _one_ "standard" sequential container instead of two
mixed up all over the place and having to explain pros, cons,
differences, history, whatnot. Going forward, given the containers will
be identical, it would help leaving just one around.
====
[1] Major source incompatibilities insofar:
* functions overloaded on both QList/QVector will stop working (easy to
diagnose, code doesn't compile; easy to fix by dropping the QList
overload, although for things like logging, what type do you end up
printing?).
* iterator stability for QList-in-array-of-pointers-mode is gone
(potentially very hard to diagnose, if it happens rarely; potentially
intrusive to fix properly).
* object lifetime issues for objects with broken special member
functions when stored in QList-in-array-of-pointers-mode -- not a bug in
QList.
My 2 c,
--
Giuseppe D'Angelo | giuseppe.dangelo at kdab.com | Senior Software Engineer
KDAB (France) S.A.S., a KDAB Group company
Tel. France +33 (0)4 90 84 08 53, http://www.kdab.com
KDAB - The Qt, C++ and OpenGL Experts
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4329 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://lists.qt-project.org/pipermail/development/attachments/20200423/52e44f25/attachment-0001.bin>
More information about the Development
mailing list