diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2020-10-16 17:08:36 +0200 |
---|---|---|
committer | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2020-10-20 09:32:22 +0200 |
commit | 3c74ba1f8b1052e684c67cbbb6f99eb4f7146f40 (patch) | |
tree | 1752893be9fae5889c42657e045d73d9d3773664 /src/corelib | |
parent | 5683c0afdaf942e81ba614bd44eda0cc59d0d7a1 (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')
-rw-r--r-- | src/corelib/tools/qlist.h | 14 |
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); |