views:

110

answers:

3

Possible Duplicate:
remove_if equivalent for std::map

Yesterday i wrote a program, which use multiset for storing elements like this:

std::multiset < boost::shared_ptr < CEntity > > m_Entities;

Then i try to use standard algorithm remove_if like this:

std::remove_if(m_Entities.begin, m_Entities.end(), MarkedForDestroy);

BUT compilation failed, because if we see in GCC 4.4 implementaion of set and multiset we see that:

typedef typename _Rep_type::const_iterator            iterator;
typedef typename _Rep_type::const_iterator            const_iterator;

I was shocked. I google this moment and better that i found that this does not contradict the standard. The same for set.

How this cannot contradict if standart algorithms doesnt work? How i can better change container?

A: 

Because multiset (and also set) are immutable containers, i.e. elements in the container cannot be changed modified in-place, they can be removed, modified, and (re-)inserted.

See, for example:

  • a different set related answer
  • section 27.3.2.1 in this tutorial

In simple associative containers, where the elements are the keys, the elements are completely immutable; the nested types iterator and const_iterator are therefore the same.

ArunSaha
I have understood this. Why this is so? Set have an order, why such problems?
den bardadym
No, they're [not](http://www.cplusplus.com/reference/stl/multiset/insert/).
Matthew Flaschen
@den bardadym: Note that `remove_if` doesn't actually "remove" the elements from the container instead it just moves the elements to the end of the container. For sequential containers moving to the end makes sense but for associative containers in which elements are stored in a sorted order, this doesn't make sense as it will break their ordering.
Naveen
@Matthew Flaschen: I know that elements can be *inserted* in a set, I did not restricted that when I said "elements cannot be modified". What I meant was elements cannot be modified in place. Thats because in [multi]set the elements themselves are keys of the underlying BST, and if the keys are modified, the BST may no longer remain a BST.
ArunSaha
@naveen: Thanks, i dont know this.
den bardadym
@Arun, there's a difference between the container being immutable (no modifications of any kind possible) and not allowing element replacements in-place.
Matthew Flaschen
@Mathew Flaschen: You are right, on literal interpretation, there is difference. But, have you seen any immutable container per your definition? Because, AFAIK, all containers allow insert and erase (http://www.cplusplus.com/reference/stl/). It would not be a "container" if it wouldn't, isn't it?
ArunSaha
@Arun, there are no immutable-only container classes in the C++ standard library, since it relies on `const` instead. However, other languages certainly have them.
Matthew Flaschen
+4  A: 

You can not use std::remove_if algorithm on an associative container. You need to a write a for loop and use the erase method to remove the elements. See this similar question remove_if equivalent for std::map for more details.

Naveen
Thanks, this is better than previous answer.
den bardadym
+1  A: 

All standard ordered/associative containers (map, set, multimap, multiset) have immutable keys (just the keys not the entire container).

As to why just look at what would need to happen every time you would change the value of the key: the key type would need somehow to notify it's container that it got changed (which would introduce a very tight and unnecessary coupling between the container & it's key type - not to mention being impossible to do for fundamental types) because the container would need to be resorted so to keep it's ordering property (which is a pretty big overhead).

Eugen Constantin Dinca