[Development] Question about QCoreApplicationData::*_libpaths

Kevin Kofler kevin.kofler at chello.at
Fri Jan 22 01:13:06 CET 2016


Marc Mutz wrote:
> 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?).

And my point is that in most cases, CoW avoids exactly that problem, 
allowing you to safely (and even thread-safely!) return newly-created data 
(i.e. NOT return a dangling reference), without having to deep-copy it. 
Model indexes are a different matter.

> 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?).

Simply assume that you can't.

> 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.

Again: Consider references always invalidated. The fact that they sometimes 
happen to keep working is an implementation detail that must not be relied 
on. Would you want QList to go out of its way to invalidate references 
somehow (if, due to a performance optimization, the data did not actually 
move)? That would go against the very performance principles you are 
fighting for.

Part of the concept of undefined behavior is that it may also appear to just 
work (and then it may also start breaking at any time). There is no 
guarantee that invoking undefined behavior will crash and burn, that would 
defeat the purpose of undefined behavior. So just consider working with 
dangling references to QList members after modifying the list to be 
undefined behavior.

If you are keeping a reference to an element of QList or QVector across an 
insert / append / prepend / remove, you are doing something wrong! Those 
references are really only intended to be used in lines such as:
myList[i] = foo;
or at most in the equivalent of a "with" block in some higher-level 
languages, i.e., e.g.:
{
  Foo &element = myList[i];
  element.foo = foo;
  element.bar = bar;
}
(You can leave off the scope braces if you want, but my point is that at 
that point you should be done using element, so you may as well let it go 
out of scope.)
Everything else is a blatant API abuse.

> 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.

In many practical cases, the alternative is to ALWAYS deep-copy (plain 
assignment in STL, explicit clone() in Java or Python), so CoW will actually 
SAVE you many of those O(n) deep-copy operations.

> 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").

I consider QSharedPointer good enough, and I really think a complete Qt 
class library should remain a goal. In particular, I also think QtAlgorithms 
should be undeprecated and extended with new algorithms. The goal should be 
that the average Qt-using developer should never have to use any STL class, 
and the Qt ones should have a friendlier API. This was already the case in 
QtAlgorithms compared to the STL algorithms, e.g., qSort had a convenient 
qSort(container) overload whereas std::sort requires you to write the ugly 
and redundant std::sort(container.begin(), container.end(), qLess<T>());. So 
switching to STL algorithms was a huge step backwards in API quality.

The std::sort API is also symptomatic of the main design issue of the STL: 
The STL API is always optimized for the complex corner case (such as wanting 
to sort only an arbitrary subset of a container), neglecting the convenience 
overloads for the common case that will matter in >99% of the cases (sorting 
the whole container). (Having to pass qLess explicitly is another issue, but 
that one is mostly a backwards compatibility issue. The bigger issue is that 
std::sort(container) just does not exist, even if you want the operator< 
comparison function the STL defaults to.) So you end up with boilerplate 
.begin() and .end() calls all over the place.

> 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.

I see only one person trolling and that's you. Everyone on this list knows 
that you love the STL and the new C++ language features in C++11 and newer 
and would like everyone to pick them up immediately, throw away everything 
else and do everything the C++11 way, which you consider the one right way. 
But things are simply not that black and white.

We also all know that you want to do very complex things with containers 
that many people (even on this list!) did not even know existed, let alone 
would have expected someone to actually try to use. Please keep in mind that 
you are not the average Qt-using developer.

> The wider C++ community ignores Qt, and I feel that's to the detriment of
> both.

I think Qt should ignore the "wider C++ community", too. The STL is really a 
completely different beast, we only share the language-level parts.

> Some try to fork the project.

Somebody forking the project is exactly what is going to happen if you throw 
away the very things that made people use Qt.

        Kevin Kofler




More information about the Development mailing list