From a3e5efa8a2f66a0171b8bf3519155c521cf68792 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Fri, 4 Dec 2020 16:05:58 +0100 Subject: [PATCH] Sequential containers: make removeIf/erase_if not detach unless needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Employ the same kind of optimization existing for removeAll/erase. Change-Id: I0781cc02d4430ceab60e6e50a5ffe6fde87be9ce Reviewed-by: MÃ¥rten Nordheim Reviewed-by: Thiago Macieira --- src/corelib/tools/qcontainertools_impl.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qcontainertools_impl.h b/src/corelib/tools/qcontainertools_impl.h index e4812eefef6..238e8a849b6 100644 --- a/src/corelib/tools/qcontainertools_impl.h +++ b/src/corelib/tools/qcontainertools_impl.h @@ -191,9 +191,17 @@ auto sequential_erase_one(Container &c, const T &t) template auto sequential_erase_if(Container &c, Predicate &pred) { + // avoid a detach in case there is nothing to remove + const auto cbegin = c.cbegin(); + const auto cend = c.cend(); + const auto t_it = std::find_if(cbegin, cend, pred); + auto result = std::distance(cbegin, t_it); + if (result == c.size()) + return result - result; // `0` of the right type + const auto e = c.end(); - const auto it = std::remove_if(c.begin(), e, pred); - const auto result = std::distance(it, e); + const auto it = std::remove_if(std::next(c.begin(), result), e, pred); + result = std::distance(it, e); c.erase(it, e); return result; }