[Development] Question about QCoreApplicationData::*_libpaths
Marc Mutz
marc.mutz at kdab.com
Thu Jan 21 11:03:08 CET 2016
On Thursday 21 January 2016 07:59:18 Mathias Hasselmann wrote:
> Am 21.01.2016 um 08:00 schrieb Marc Mutz:
> > On Thursday 21 January 2016 05:24:35 Kevin Kofler wrote:
> >> Marc Mutz wrote:
> >>> On Wednesday 20 January 2016 22:50:43 Kevin Kofler wrote:
> >>>> All these are horrible and error-prone hacks that have obvious
> >>>> lifetime issues. You are complaining about Qt containers because the
> >>>> detaching can invalidate iterators. Well, the lifetime issues you
> >>>> introduce with the above proposed solutions are much worse! And a
> >>>> caching mutable member also destroys thread-safety (in addition to
> >>>> the obvious lifetime issue that the next call surprisingly
> >>>> invalidates your existing reference).
> >>>
> >>> One word: QModelIndex.
>
> Sorry Marc, no. Really.
>
> QModelIndex is entirely unrelated to the problem Eike raised.
I was replying to Kevin. QModelIndex exactly fits his complaints about const-&:
It's a reference used in interfaces. As soon as you store it, though, it may
become stale at the next opportunity (like when calling a virtual function).
You're supposed to store them in QPersistentModelIndex in that case. But QPMI
is extremely expensive.
Compare that to:
const std::vector<QFoo> & foos();
You can either assign the result to a const-& (=QModelIndex case), get max
performance, but suffer from possible invalidation if you call out to unknown
code. Or you store it in a copy, incurring the copy, but insulating yourself
from changes to the original object (=QPersistentModelIndex case).
They really are two instances of the same class of problem: dangling
references. And you cannot escape that problem. Not in C++, and not in other
imperative languages, either. If you replaced QMI with an int, as you could,
for QAbstractListModels, then you'd have exactly the same problems of
invalidation (who updates your int if the row it points to gets removed?).
> I highly reward your expertise and what you are doing for Qt, and I
> really don't want my high opinion of you being spoiled. So please grab
> fine cup of tea, take a comfortable seat and spent some time on
> understanding, why this discussion took such dramatic shift away from
> its initial topic, why you are receiving such heat. Also please take
> some time to recall what other properties but performance are important
> when designing general purpose libraries.
If I have given the impression that it's just about speed, I'm sorry.
Speed is one argument, yes. If the Qt class had that much more (useful, to
avoid counting indexOf() as a feature) features than the std counterpart, I
would be the last to talk about replacing it. QString e.g. has superior
Unicode handling. We can discuss how it should be laid out (CoW or not, say),
but no-one challenges the very right of QString to exist.
But if a Qt class has only half the feature of its std counterpart and at the
same time performs worse, then the question needs to be asked whether that
class really needs to be in Qt.
So yes, I cannot shake the deeply-ingrained C++ principle of "don't pay for
what you don't use". It's what keeps C++ relevant these days, despite its
rough edges.
But speed is not the only reason:
I don't like Q_FOREACH not just because it performs badly, which it really
doesn't, usually, for Qt types, but because it makes it hard to reason about
the code (why is a copy taken? Is is needed?).
I don't like QThread being a QObject because it makes misusing the API all too
easy.
I don't like QList because only experts can tell which guarantees it provides
for any given type (can I keep references into the container across appends?).
It's also the only container in the C++ world where iterator and reference
validity are not synonyms: An append where capacity() == size() invalidates
iterators in both QList modes, but only invalidates references in vector-with-
padding mode.
I don't like CoW because it creates long-range effects that are also the
underlying reason we don't like global variables. It also makes any complexity
specifications moot, because you never know whether you will incur that extra
O(N) detach.
I don't like QSharedPointer because it does nothing better, and lot of things
worse, than shared_ptr and was only added (long after boost::shared_ptr and
tr1::shared_ptr came into existence) because of an overly strict sense of BC
that extends beyond the Qt libraries (aka "we can't use boost/std in our
APIs").
As for why I am receiving such heat: I don't. It's the same couple of persons
every time that troll around. I should get better at not feeding them, sure.
The people that matter in Qt development, however, take this constructively,
even when they disagree about the whens and hows. I take the extreme pov in
these discussions, because someone has to. The wider C++ community ignores Qt,
and I feel that's to the detriment of both. Some try to fork the project. I
prefer to work within it, as someone who was but a consumer of Qt API for
(still) most of his professional career, but who also "gets" boost and std.
One reason why Effective Qt doesn't really get off the ground is that it's often
easier to just fix the problem at the root instead of writing about it.
> QModelIndex is perfectly fine if you use it as intended, as
> short lived reference into a tree model.
Exactly.. And my point is:
quote =~ s/QModelIndex/const-&/;
quote =~ s/tree model/object/;
Thanks,
Marc
--
Marc Mutz <marc.mutz at kdab.com> | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts
More information about the Development
mailing list