Does bulk memmove speed up std::remove_if? (No.)

https://lobste.rs/rss Hits: 10
Summary

This morning I was reading the umpteenth std-proposals thread proposing some variety of unstable_remove and it occurred to me that one odd thing about a swap-and-pop-based unstable_remove is that it tends to replace large swaths of contiguous removals by reversing the elements that are kept. For example (Godbolt): template<class BidirIt, class Pred> BidirIt unstable_remove_if(BidirIt first, BidirIt last, Pred pred) { while (true) { first = std::find_if(first, last, pred); if (first == last) return first; while (true) { --last; if (first == last) return first; if (!pred(*last)) break; } *first++ = std::move(*last); } } int main() { auto in234 = [](int x) { return 2 <= x && x <= 4; }; std::vector<int> v = {1,2,3,4,5,6,7,8,9}; v.erase(unstable_remove_if(v.begin(), v.end(), in234), v.end()); // v is {1,9,8,7,5,6} } It would be more aesthetically pleasing to produce {1,7,8,9,5,6}: for trivially copyable elements, this would be a single memmove. In a sense, “reversing the elements” is extra work that we might save time by avoiding. But to avoid that work, we might have to do even more work in the form of bookkeeping. I haven’t attempted to benchmark any such change to unstable_remove. But the same aesthetic consideration applies to the ordinary, stable std::remove_if. Traditionally it’s a loop over operator=, like this: template <class FwdIt, class Pred> FwdIt smooth_remove_if(FwdIt first, FwdIt last, Pred pred) { FwdIt dfirst = std::find_if(first, last, pred); if (dfirst != last) { for (first = std::next(dfirst); first != last; ++first) { if (!pred(*first)) { *dfirst++ = std::move(*first); } } } return dfirst; } But what if we “chunked” the writes to *dfirst, like this? template <class FwdIt, class Pred> FwdIt chunky_remove_if(FwdIt first, FwdIt last, Pred pred) { FwdIt dfirst = std::find_if(first, last, pred); if (dfirst != last) { for (first = std::next(dfirst); first != last; ++first) { if (!pred(*first)) { FwdIt sfirst = first; first = std::find_if(std::next(first), ...

First seen: 2026-05-24 05:48

Last seen: 2026-05-24 20:59