[Development] Question about QCoreApplicationData::*_libpaths
Bubke Marco
Marco.Bubke at theqtcompany.com
Sat Jan 16 02:40:02 CET 2016
On January 16, 2016 00:44:57 Kevin Kofler <kevin.kofler at chello.at> wrote:
> Marc Mutz wrote:
>
>> On Friday 15 January 2016 03:58:12 Kevin Kofler wrote:
>>> So why not just add a QOptional that works the same as std::optional?
>>
>> a) because we can't (we don't yet require the necessary language features)
>
> A QOptional<T> that works with Qt's implicitly-shared data objects (such as
> QStringList, which is what it is wanted for here) only really needs this:
> T data;
> bool present;
> (I guess that order will give the better memory layout than the opposite
> order.) If present is false, you just put a default-constructed T into the
> (ignored) data field, which will simply have a null d-pointer and thus cost
> you almost no time to construct. I don't see what further language features
> are needed for us.
>
>> b) because once introduced, people will add all kinds of Qt-specific stuff
>> to it, making it impossible to replace it with std::optional down the
>> road. And since it will be good enough for the low demands of Qt
>> development, it will no longer see development and fall behind the state
>> of the art.
>
> So what? Qt users are not forced to use it, and I'm sure several will, maybe
> BECAUSE of the "all kinds of Qt-specific stuff" that people actually find
> convenient.
Actually this convince is hurting you if you need performance. I would prefer the convenience on top of lower level api.
>> <rant>
>> Consider QVector: it has been Qt-ifed by both adding (technically) useless
>> duplicate Qt-ish API, CoW, and a Qt-specific type classification scheme
>> plus corresponding optimisations that make it very hard to argue for
>> std::vector use instead. The Qt community had two decades where they could
>> have influenced the direction std::vector would take so it could allow the
>> same optimisations that QVector has, but the time and energy was instead
>> put into re-writing the containers for every major release (yes, for Qt 5,
>> too, and Thiago's Qt 6 QVector again looks much different from the Qt 5
>> one).
>
> But the Qt-ish API and the CoW are exactly what makes the Qt containers NICE
> to use, unlike the STL. I have found myself more than once using QtCore in a
> project solely and explicitly for the container classes! They are what makes
> C++ a nice-to-use language.
It makes also easy to shoot yourself in the foot. The Qt containers love to malloc. ;-)
I really prefer the the proposed ranges API.
>> The CoW makes QVector slow and increase code size, leads to hidden
>> detaches that not even Qt experts regularly avoid in their daily work, and
>
> Well, I am well aware of the issue, and know to use e.g.:
> static_cast<const QVector &>(vec).first()
> when needed. (I guess this is actually more efficient than the popular
> .at(0) workaround. It is definitely not less efficient.) But normally I will
> just always operate on const data structures (usually const references) when
> I'm not writing to them, so I don't have to cast anything. (And of course,
> when I'm writing to them, chances are the detach is exactly what I want or
> need.)
>
>> doesn't even work properly because you can take iterators into a QVector
>> and, after copying the vector, change both copies through the iterator
>> into the first. That is a conscious trade-off because making the container
>> unsharable, as it must become once it hands out iterators, would make CoW
>> fail to take effect _all the time_. But it leads to careless copying of
>> QVectors that also doesn't really help with porting to std::vector.
>
> So don't use iterators into QVector, use indexes, it's a random-access
> container. The non-const operator[] that you use then DOES detach when
> needed. (And of course, for read-only iteration, foreach works great.)
> The only container type where I found iterators to be truly useful is maps
> (QMap, QHash, etc.), where the iterator can give me both key and value at
> once and saves me the key lookup.
I prefer algorithms which are based on iterators to handwritten loops. They are easier to parallise in the future too.
>> All the while - and I don't believe I'm saying this - std::vector *blazes
>> the trail* with move semantics, emplace_back and stateful allocators
>> (making QVarLengthArray all but useless). Does QVector use move semantics?
>> No.
>
> Move semantics are mainly an ugly way to avoid copies if you don't have CoW.
> With CoW data structures, all you save through move semantics is the
> reference counting. And move semantics make it easy to shoot yourself in the
> foot. (Either you leave behind an invitation for a use-after-free bug, or
> you end up swapping instead of assigning, which is also a pessimization.)
In my opinion move semantics are about ownership. After using them for some time I really like them to manage resources.
Atomics on the other side can produce strange performance bugs with false sharing. I don't believe they are the future in a many core environment where you share cache lines very often.
>> Does QVector have emplace_back? No.
>
> Just like the move semantics, this is also an ugly and complicated way to
> avoid a copy if you don't have CoW or merely save the reference counting if
> you do.
But how is cow working together with the prefetcher. If I have my data outlined in a continuous way like a struct in vector it will be much faster than a pointed array.
I really like emplace. I construct objects in a vector which cannot be copied. So the vector is owning all the resources.
>> Does QVector have an allocator, even one that, citing Alexandrescu,
>> actually deals with allocation? No.
>
> For the average programmer, an allocator is just an obscure thing that shows
> up as a template parameter in all the error messages making them ugly and
> unreadable.
>
> The fact that Qt containers only have the template arguments that are
> intuitively templated on (e.g., QVector has only the contained type as a
> template parameter) is really a feature, not a bug.
>
>> Does QVector, even with Q_PRIMITIVE_TYPE payloads, expand to less code as
>> std::vector? No: https://codereview.qt-project.org/145587 (comment from
>> 01-14 11:21).
>
> So there is room for improvement there. But in the end, this is not going to
> be the deciding factor for which implementation to pick for most
> programmers. And in the end, you need to compare QVector with class
> libraries in programming languages that offer comparable convenience, not
> with the C++ STL.
Hmm most other languages I know provide more convenience than Qt but are slower. I think you pick C++ in the context of speed. So we should provide a wrapper around std vector with cow.
> If you try to force programmers to use the STL, chances are they will rather
> just switch to some other programming language that offers the semantics
> they expect.
I know many C++ who avoid Qt because we user or own containers. It really depends not everybody has the same taste or needs. I think we should provide both levels.
>> Does QVector have a debug mode comparable to that of std::vector
>> implementations? Nope.
>
> I never had any need for that.
>
>> Or: The only reason I ever used std::list was to use its splice() feature.
>> Does QLinkedList have splice()? No, of course not. Because it _cannot_
>> (it's CoWed: how do you take ownership of nodes if the they are shared? By
>> copying all other nodes in a detach()?).
>
> Then use std::list if it suits your use case better. Just don't force
> everyone else to use it.
>
> Personally, I also don't normally have a use for QLinkedList, QList suits my
> needs just fine. :-p (In fact, QList was changed from the linked list it was
> in Qt 3 to an array of pointers in Qt 4 exactly BECAUSE that's the more
> efficient data structure in most practical applications.)
QList is really a trap.
struct Entry {
QString text;
bool isHtml;
} ;
QList<Entry> list;
Do you see the problem?
> And I simply find the Qt containers to be much nicer to work with as a
> whole. In fact, I recently had to use std::priority_queue for a (QtCore-
> based) project of mine, a container class that sadly is not implemented in
> Qt (*). After attempting to use it directly and cursing about it, I ended up
> implementing a Qt-style wrapper around it:
> * My data class simply multiple-inherits from public QSharedData,
> public std::priority_queue<T>.
> * My public class contains a QSharedDataPointer of the above, renames the
> methods to names matching QQueue, and in particular adds a dequeue()
> method that does both top() and pop(). Null objects (null d-pointer) are
> also handled gracefully (the const methods fake an empty queue, the
> enqueue (= STL push) method allocates the d-pointer).
> So, a few lines of boilerplate, and suddenly the API becomes usable, and CoW
> just works. Incidentally, the CoW was also the only way I found to avoid a
> copy of the whole queue while initializing while keeping C++98 compatibility
> (so no move or swap):
> * I need to initialize my priority_queue from a list (actually a QList :-)
> but I would have the same issue with QVector or even std::vector).
> * There is no push method that takes a whole list of items.
> * So I can only:
> - either push every item one at a time, which sorts them less efficiently
> than a bulk insert,
> - or use the constructor that takes iterators, which then leaves me with a
> whole std::priority_queue to copy. My CoW wrapper avoids that copy.
> * And my API wrapper actually accepts the QList (or actually any list type
> with constBegin() and constEnd() methods) directly instead of requiring
> iterators.
>
> (*) I did find one third-party QPriorityQueue class, but it was just a
> wrapper around std::priority_queue that was neither CoW nor had API
> consistency with QQueue, so it was better to implement my own.
So why we force CoW on people. Most of the time I don't need it. And I don't need atomics if CoW is handy.
We should provide a low level version too.
>> This is why we need to stop duplicating std API. It's not Qt's core
>> competency to meddle with things we only have a half-interest in. It's fun
>> to write QOptional. Until it isn't anymore. And then the (Qt) world needs
>> to live with the poor-man's std::optional for the next few decades.
>
> I think having more Qt containers would actually be a good thing, not
> something to be scared of.
It really depends what you want to do. I would prefer it we had a CoW wrapper around std vector.
Best of both worlds.
> Kevin Kofler
>
> _______________________________________________
> Development mailing list
> Development at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development
--
Sent from cellphone, sorry for the typos
More information about the Development
mailing list