summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qlist.h
diff options
context:
space:
mode:
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);