Namespaces
Variants
Views
Actions

Talk:cpp/algorithm/remove

From cppreference.com

Where in the standard is a requirement stating that the predicate for remove_if should not modify the objects passed to it? Benjamin Lindley 22:50, 27 April 2012 (PDT)

It looks like there are some footnotes in 25.1 that describe general constraints on algorithms -- perhaps these are the source of that claim?
"4. For purposes of determining the existence of data races, algorithms shall not modify objects referenced through an iterator argument unless the specification requires such modification."
"8. ... The function object pred shall not apply any non-constant function through the dereferenced iterator."
--Nate 05:11, 28 April 2012 (PDT)
Yes, §25.1[algorithms.general]/8 (/7 in C++03) is almost certainly what the predicate template refers to. --Cubbi 07:36, 28 April 2012 (PDT)
I see. That upsets me. I wonder why they considered such a requirement necessary. --Benjamin Lindley 09:19, 30 April 2012 (PDT)
Maybe the standards committee is secretly trying to make C++ a functional programming langauge. But seriously, it doesn't seem to unreasonable to require that something called a 'predicate' not have side effects. --Nate 15:40, 30 April 2012 (PDT)

[edit] Mentioning file deletion overload?

Should this page mention that std::remove also has a unrelated (const char *) overload that deletes disk files? -- Myria (talk) 16:08, 2 June 2016 (PDT)

good point! --Cubbi (talk) 20:10, 2 June 2016 (PDT)

[edit] No invalidation of interators

We should mention that std::remove and std::remove_if do not invalidate iterators.

The erase-remove idiom relies on this:

#include <vector>
#include <algorithm>
#include <cassert>
 
int main()
{
  {
    std::vector<int> vec{1, 2, 1, 3, 1, 4, 1, 5, 1};
    auto e = vec.end();
    auto rem = std::remove(vec.begin(), vec.end(), 1);
    assert(e == vec.end());
 
    vec.erase(rem, vec.end());
    //assert(e != vec.end()); // this will usually be hold
  }
  {
    std::vector<int> vec{1, 2, 1, 3, 1, 4, 1, 5, 1};
    vec.erase(std::remove(vec.begin(), vec.end(), 1), vec.end()); // it is not specified which argument is evaluated first!!!!!!!
  }
}


The last line of code only works if vec.end() is not changed (invalidated) before and after executing std::remove. This is important, because we do not know which argument is evaluated first.