summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qlist.h
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2020-10-16 17:08:36 +0200
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2020-10-20 09:32:22 +0200
commit3c74ba1f8b1052e684c67cbbb6f99eb4f7146f40 (patch)
tree1752893be9fae5889c42657e045d73d9d3773664 /src/corelib/tools/qlist.h
parent5683c0afdaf942e81ba614bd44eda0cc59d0d7a1 (diff)
QList::removeAll: make it generic
This is a bit more tricky than expected because we support passing references to objects that are into the list itself (for instance, list.removeAll(list.front())). For those objects we have to take copies. This is fine, but the moment we make the function generic, that's going to fail when passing arguments of types that cannot be copied, such as arrays (e.g. stringList.removeAll("hello")). For those, keep a reference, as they cannot be aliases into the list anyhow. [ChangeLog][QtCore][QList] The removeAll and removeOne methods now take an object of any datatype -- and not just the list's own value type. This allows for heterogenous removal inside QLists. Change-Id: I0c447770bbc7ff0ff4bb4c0e35081414c5ff963e Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/tools/qlist.h')
-rw-r--r--src/corelib/tools/qlist.h14
1 files changed, 11 insertions, 3 deletions
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 185bcc5086..3094bcba97 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -319,14 +319,22 @@ public:
// QList compatibility
void removeAt(qsizetype i) { remove(i); }
- qsizetype removeAll(const T &t)
+ template <typename AT>
+ qsizetype removeAll(const AT &t)
{
const const_iterator ce = this->cend(), cit = std::find(this->cbegin(), ce, t);
if (cit == ce)
return 0;
qsizetype index = cit - this->cbegin();
- // next operation detaches, so ce, cit, t may become invalidated:
- const T tCopy = t;
+
+ // Next operation detaches, so ce, cit may become invalidated.
+ // Moreover -- unlike std::erase -- we do support the case where t
+ // belongs to this list, so we have to save it from invalidation
+ // by taking a copy. This is made slightly more complex by the fact
+ // that t might not be copiable (in which case it certainly does not
+ // belong to this list), in which case we just use the original.
+ using CopyProxy = std::conditional_t<std::is_copy_constructible_v<AT>, AT, const AT &>;
+ const AT &tCopy = CopyProxy(t);
const iterator e = end(), it = std::remove(begin() + index, e, tCopy);
const qsizetype result = std::distance(it, e);
erase(it, e);