[Development] QtCS 2017 QtCore sessions

Giuseppe D'Angelo giuseppe.dangelo at kdab.com
Mon Oct 23 01:29:22 CEST 2017

Some other comments here and there,

Il 10/10/2017 14:49, Thiago Macieira ha scritto:
> [we combined the main and containers session; we did not have time for
> QIODevice]
> == Intro ==
> Suggested topics:
> * QIODevice for Qt 6
> * adding std::hash for Qt types

As in: we're OK that this should be done.

> * expanding the hash seed to 64- or 128-bit

But how, without breaking all the existing code? (Also, is it worth it?)

> == Use of standard C++ API ==
> We will not add compilers that are worse than what we have today.
> * If all the compilers we have support things like std::mersenne_twister, then
> all will
> * We can add hard-fail configure test
> * Should we start migrating from QSharedPointer to std::shared_ptr?
> ** Deprecate
> ** Deprecate QScopedPointer

Just noticed that we _do_ have QSharedPointer in our API, e.g.:


(Yes, it's a totally and utterly broken signature, but that's it). 
Anyhow, in favour of deprecating 
QSharedPointer/QWeakPointer/QScopedPointer, as well as the atomic 
classes, and any other piece of functionality which has a _perfect_ 
replacement coming from the Standard Library.

> * What about API from C++17/20 that we'd like to use?
> ** Try to backport the API into a QtPrivate namespace (if it's been
> standardised) unless we want to add significant functionality a la QStringView
> ** If it's not standardised yet, use Qt-style naming

Is it just as a general policy or was some specific request raised?

> * API naming
> ** std:: API naming is subtly different from Qt API (hopefully nothing that is
> confusing or misleading)
> ** We could try to create wrappers (container.empty() → container.isEmpty())

Wrappers for the STL classes, that is?

> == Modifiers vs getters for QString/QStringView/QByteArray ==
> We don't want people to write:
>    str = std::move(str).simplified()
> We want instead:
>    str.simplify()
> So we want to add the full set of modifiers.

In the sense that we want BOTH the modifier (imperative present) and the 
non-modifier copy (indicative simple past), right?

> Do we want to add freestanding functions that may operate on std::string and
> other string types?
> * Like qSimplify()
> * Polluting namespace

Shove them in a namespace >:-)

> * They'd all need to be inline and some could be big

Why they need to be inline?

> * freestanding brings in ADL and could introduce unexpected isues
> * We think members are cleaner and we don't want to add these
> * However, we already have some of those! qStartsWith
> ** Global namespace *and* documented

The point of having those, however, is to make them work with _any_ 
string-viewable type, including those we can't add functions to (e.g. 
std::u16string). So, are we saying we don't care?

> ** foo.startsWith(bar) vs qStartsWith(foo, bar)
> ** Same conclusion, probably mark \internal, namespace them
> *** But review the changes to see what our arguments were on making them
> public

Two birds with one stone:
* the argument above (we've now got functions acting over types we don't 
/ can't control)
* and the fact that this way we can avoid adding methods everywhere, so 
we don't need to add the string function to all of our string classes. 
(This last argument is kind of weak, though, but I see the maintenance 
and testing burden.)

> == QStringView ==
> * NEVER return QStringView (but QRegularExpression wants to)
> ** Consequence of "never return a reference" (but containers do)

The C++ community is freaking out on string_view and it's right now in 
the "love it or hate it" mood. I don't get any of the hate -- personally 
I think it's just because we finally have a reference type that we 
_want_ to use everywhere, and so we now get the problems of reference types.

So I'm not buying the "NEVER" return exactly -- you can, but you need to 
document what's the lifetime expectation of your QStringView (in other 
words, what's it tied to).

> ** Lifetime issues
>      auto s = lineedit.text().left(n);
>      s valid?

A good chunk of these lifetime issues will likely be detectable via 
linters. No, not volunteering about adding the checks to clazy (but I 
hope that such checks will be added to clang-tidy and)

> == Containers ==
> You cannot have all three:
> # Implicit sharing
> # Performance
> # Data-compatibility with std:: containers

At this point in time, with the resources we have developing the 
containers (pretty much only Thiago at this point?), I'd rather go with 
1+3. We will never be able to get rid of 1. So instead let's push away 
the implementation burden, get all the features implemented "for free", 
make the dealing with all the corner cases SEP (e.g. the infamous 
clear/resize/reserve behaviours, QMap insertion order, ...), and live 
with the small performance hit.

> QList:
> *  [https://codereview.qt-project.org/194984 QUIP 9]
> Conclusions:
> * If we have QStringView, QArrayView, QByteArrayView, we don't need
> fromRawData()
> * We use qssize_t everywhere

Not entirely buying this... Has anyone attempted to do the change, just 
for the sake of it? How many millions of lines of code are going to emit 
warnings, if not break altogether?

> Containers relevant:
> * QArrayData-based containers: QString, QByteArray, QVector
> ** Backed by the same template implementation (QArrayDataPointer)
> ** They grow to 3*sizeof(void*): {d pointer, begin pointer, qssize_t };

For QString, where do you store the SSO?

> ** Implementations:
>      template<typename T> using QVector = QVectorImplementation<T, RefCounted>;
>      template<typename T> using QExclusiveVector = QVectorImplementation<T,
> NotRefCounted>;
>      QExclusiveVector v;
>      v.resize(1024);
>      auto ptr = v.data();
>      // instead of: auto ptr = const_cast<QChar *>(v.constData())
>      QVector v2 = std::move(v);
>      v = std::move(v2);

With proposal 1+3 above, QExclusiveVector == std::vector.

> * QHash, QMap
> ** Wrapping std::{unordered_}map may be acceptable
> ** Would we want to use qHash as the HashFunction with std::unordered_map?

It's not even a choice...? If QHash wraps std::unordered_map it will use 
qHash (existing code must work). And by exposing the underlying 
container, one can splice a QHash into a std::unordered_map with a 
different hasher, if one desires so. (Ditto with QMap.)

My 2 cents,
Giuseppe D'Angelo | giuseppe.dangelo at kdab.com | Senior Software Engineer
KDAB (UK) Ltd., a KDAB Group company | Tel: UK +44-1625-809908
KDAB - Qt, C++ and OpenGL Experts

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4007 bytes
Desc: Firma crittografica S/MIME
URL: <http://lists.qt-project.org/pipermail/development/attachments/20171023/0fbaeefd/attachment.bin>

More information about the Development mailing list