tags:

views:

329

answers:

6

In the book 'C++ In A Nutshell', there is the following example code

std::vector<int> data
...
std::erase(std::remove(data.begin(), data.end(), 42),
  data.end());

I thought that 'erase' was a member function, so shouldn't that be 'data.erase' rather than 'std::erase'? Is there some way the c++ compiler can tell what member you wanted to call a member function on, or did the book omit any documentation of an erase template function, or is the example wrong?

+7  A: 

erase is a member function. The sample provided is incorrect.

Pavel Minaev
A: 

Edit: Sorry their is no generic erase, just double checked

lkristjansen
There's no generic algorithm `erase`.
Pavel Minaev
... not even in `<algorithm>` (go ahead, try it).
Pavel Minaev
yes i was incorrect saying that there was a generic erase algorithm(i remembered wrong). but there is a algorithm header in the standard library. Which includes alot of generic algorithms(find, includes, etc.), which works with the various stl containers.
lkristjansen
As a general rule of thumb: algorithms in STL operate on iterators, and through that they can change the contents of a container, but they cannot change the container itself. Erase is a method that modifies the size of the container and as such cannot be implemented in terms of iterators, but needs access to the container itself.
David Rodríguez - dribeas
@dribeas: but note that there are `insert_iterator`s, which can change the size of the container. There are no matching `delete_iterator`s, but there's no real reason there couldn't be.
Jerry Coffin
Insert iterators are categorized as output iterators, which is an existing and well-defined category. They don't add anything to the contract of that category. What would "delete iterators" be categorized as?
Pavel Minaev
+6  A: 

There is no std::erase. std::map::erase, std::list::erase exists. But no std::erase exists.

Look this question about phantom std::erase.

Alexey Malistov
To be specific, all sequence and associative containers provide member `erase()` (it's part of their requirements), as well as `std::basic_string`.
Pavel Minaev
+3  A: 

Yes, erase is a member function, so it should be data.erase() instead of std::erase().

Jerry Coffin
+3  A: 

You observation is correct. 'Erase' should be a member function. Only a member function on a container can change the memory size of that container.

Phillip Ngan
A: 

There is an algorithm called std::remove. And calling erase on the data structure. remove moves all the elements to be erased to the end of the iterator range and returns the first element to be removed. Returns end() if the element could not be found.

So then you call erase on range starting with the return value of std::remove and the end of the data structure.

See: http://www.sgi.com/tech/stl/remove.html

Note that remove won't work with ordered datastructures, as the elements can't be rearranged.

remove is linear, and so would be removing a vector from up to the end. As it wouldn't need to bubble up the elements after the elements to be removed.

std::vector<int> data
...
data.erase(std::remove(data.begin(), data.end(), 42), data.end())

compared to something like this which is O(N**2)

std::vector<int> data
...
for ( i = data.begin(), i != data.end(); ++i ) {
  if ( *i == 42 ) data.erase( i ) ;
}
Eld
Read the question again. It uses std::remove. You don't have to say "what looks what they wanted", because that's what they used.
Paul Tomblin