>>Even our API guidelines stipulate that you should make common things easy and >>not-so-common things possible. Sharing is _not_ common and it need not be as >> easy as common tasks. I
Maybe for you, but in my works, sharing _is_ common, convenient and safe. And overal usage of COW is one of the concept that makes Qt stand apart. >From my POV, COW largely pay off its minimal performance cost. When performance is a high priority, _an uncommon case_, then using alternate containers is always possible and we don't need Qt for this. And when size matters, have this in mind: sizeof(std::vector<int>) == 32 sizeof(QVector<int>) == 8 sizeof(QList<int>) == 8 (VC++ 64bit) Philippe On Mon, 20 Mar 2017 09:09:57 +0100 Marc Mutz <[email protected]> wrote: > On Sunday 19 March 2017 19:48:36 Thiago Macieira wrote: > > On sábado, 18 de março de 2017 15:32:55 PDT Marc Mutz wrote: > > > On Saturday 18 March 2017 19:30:35 Thiago Macieira wrote: > > > > QVector<MyType> someFunction() // out-of-line > > > > { > > > > > > > > QtExclusive::QVector<MyType> vector; > > > > [ operate and populate vector ] > > > > return vector; // automatic move > > > > > > > > } > > > > > > > > in user code: > > > > QtExclusive::QVector<MyType> vector = someFunction(); // > > > > > > > > automatic move [ mutate some more ] > > > > > > Breaks (N)RVO. > > > > How? > > Returned Type != (Declared) Return Type != Expected Type (by caller) > > For NRVO, all three must be identical, for RVO the last two. > > > > And since the code outside has no clue about whether the code inside the > > > function creates a shared or unshared QVector, the compiler will again > > > have to emit the whole QVector copy constructor/detach code (as dead > > > code) at the call site. You promised this would be gone in Qt 6 because > > > of the removal of the unsharable state. > > > > QtExclusive::QVector's move constructor for QVector always needs to emit > > copying code, since it doesn't know whether the data is shared or not. > > There's no way around that. > > > > QVector's move constructor for QtExclusive::QVector simply adopts the data > > and starts reference-counting. > > Sure, I understand that. It's the misuse of QVector when exclusive QVector > was > needed that is the problem: > > > You could argue that a function that always returns an unshared vector > > could return QtExclusive::QVector. > > Exactly that. > > > But we should not allow that in our API > > any more that we allow returning references. > > Yes, that was my fear. > > The exclusive split sounded like a good idea, like unique_ptr vs. shared_ptr, > one that could actually win me over to support keeping any form of Qt > container at all, long-term. Until right now. > > If you would propose to make QVector exclusive, maybe with SOO, and provide > QSharedVector, but to default to QVector in API, you would probably have me > on > board. > > It's a fallacy to think that there's a lot of need to return a shared > collection from APIs. Either you create the collection on request, then an > exclusive collection would be preferable, as returning it from a function is > free[1], or you "return" internal state, in which case returning some form of > view (incl. the case of simply adding begin()/end()) would be the way to go > (cf. https://codereview.qt-project.org/150658). > > Even if your pov is that you should always return an owning collection in > these cases, and that it therefore has to be a shared one, existing Qt code > (QObject::children()) shows that even CoW is too slow in these cases > (children() returns by const-&). If QObject was iterable as a container of > QObject*, that would both be more convenient as well as faster). > > [1] yes, _is_. Ville may correct me if I'm wrong, but afaiu, C++17 makes > (N)RVO mandatory. Sorry, GCC, you'll have to finally do something about your > broken NRVO. > > > > > Why not std::vector? Because of the ability to put it back into shared > > > > mode, > > > > > > std::shared_ptr<const std::vector> > > > > One level of indirection too many. We've been over this. > > iow: you'd rather pay some large overhead every time than pay a larger one > only in cases where it's needed. And this is where we fundamentally disagree. > > Even our API guidelines stipulate that you should make common things easy and > not-so-common things possible. Sharing is _not_ common and it need not be as > easy as common tasks. Iteration, builing a container from scratch, returning > by NRVO from a function, these are common things. And CoW pessimises such > common things - not only performance-wise, but also conceptually: std::vector > doesn't need qAsConst when used with ranged for loops, std::vector doesn't > invalidate iterators when copied from... > > Thanks, > Marc > > -- > Marc Mutz <[email protected]> | Senior Software Engineer > KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company > Tel: +49-30-521325470 > KDAB - The Qt, C++ and OpenGL Experts > _______________________________________________ > Development mailing list > [email protected] > http://lists.qt-project.org/mailman/listinfo/development _______________________________________________ Development mailing list [email protected] http://lists.qt-project.org/mailman/listinfo/development
