[Development] RFC: Containers member functions for algorithm

Philippe philwave at gmail.com
Thu Mar 23 10:50:03 CET 2017

I hardly imagine a "container" api without a "contains()" member. What I
would call good sense. Qt already has this, std not.

The other member that makes sense, if "indexOf()"... Qt already has this.

For the rest, free functions provide more flexibility.

>> I realize that QtCreator already has helper functions:

Similar convenience wrappers are found in many applications...
It would not harm to have such wrappers in Qt.


On Thu, 23 Mar 2017 08:32:14 +0100
Olivier Goffart <olivier at woboq.com> wrote:

> Hi everyone,
> I have been wondering if we should enhance Qt container with member functions 
> to help using some of the standard algorithm.
> a peace of code is better than many words. We would be able to do:
> myList.sort();
> //or 
> myList.sort([](auto &a, auto &b){ return a.member < b.member; });
> if (myList.contains([&value](const auto &elem){ return elem.id == value; }))
>    doSomething();
> myList.removeIf([&](const auto &elem) { elem.field > someValue; })
> And these are a tad more convenient than using the standard library directly.
> Compare to:
> myList.erase(std::remove_if(myList.begin(), myList.end(), 
>                   [&](const auto &elem) { elem.field > someValue; }),  
>                  myList.end());
> Of course, myList can be a QList, a QVector, or a QVarLenghtArray
> Here is an overview in how this could be implemented, should we want this:
> https://codereview.qt-project.org/#/c/189313/
> Anyway, before I continue working on this patch, I want to know if this is 
> even something what the Qt Project wants.
> The reason we would want it are obvious: convenience.
> In the mean time, the standard is working on the so called range library. So 
> in C++20, you could maybe just write   std::sort(myList).  
> But that's in the far future, and I want to be able to use it now.
> There are already convenient range libraries that makes things convenient 
> available on github, but that's another dependency and the compatibility 
> guarantee are not the same.
> The reason we would not want this is because this makes our containers too 
> convenient. The implementation of QVector is inferior to the one of 
> std::vector. (for example, it cannot contains move-only types).
> Right now, it is quite easy to replace QVector by std::vector. But adding nice 
> feature to QVector may mean a reason to keep QVector longer in Qt6 instead of 
> changing to standard containers.
> Marc already expressed his opinion on the gerrit change, pointing out that we 
> deprecated qSort and the qt algorithm for a reason: the quality of the std 
> algorithm was better than the naive implementation in Qt. However this is just 
> a helper around the std algorithm implementation.
> Why did we not added these function already in Qt 4.0?  I was not there yet, 
> but I believe this might have been for technical reason: MSVC 6 was still 
> supported until Qt 4.5, which mans no template member functions.
> Also sort needs an operator<, and non-template function might be instantiated 
> even if not used.
> So with this mail I would like to know what you think. If you think this is a 
> good idea or a terrible one.
> Once we agreed the general idea is good, we can go into the details of the API 
> or implementation. 
> On this WIP patch, I only took the algorithm that were most used within Qt and 
> QtCreator.  I realize that QtCreator already has helper functions:
> https://code.woboq.org/qt5/qt-creator/src/libs/utils/algorithm.h.html
> That's I think one proof that shows that this would be useful.
> I am wondering if findIf shoud return a pointer or an iterator.
> Returning a pointer allow things like
>   if (auto *elem = myContainer.findIf([&](const auto &elem) 
>                                       { return elem.foo == bar; }))
>       elem->plop = myPlop;
> But does not work well if you want to find-then-remove:
>   auto it = std::find(myContainer.begin(), myContainer.end(),
>                       [&](const auto &elem) { return elem.foo == bar; });
>   if (it != myContainer.end()) {
>       myResult = *it;
>       myContainer.erase(it); // not possible if 'it' was a pointer
>   }
> So I'm afraid there will be much discussions and bike-shedding
> Regards
> -- 
> Olivier
> Woboq - Qt services and support - https://woboq.com - https://code.woboq.org
> _______________________________________________
> Development mailing list
> Development at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development

More information about the Development mailing list