Re: STL - erasing from a set
 
Am 17.11.2010 22:03, schrieb A B:
Hello,
I am trying to do a "set difference" operation, to trying to take some
elements (objects) out of a set. I wrote a small sample program to
test it.
--------------------------------------
#include<iostream>
#include<cstdlib>
#include<set>
#include<vector>
#include<algorithm>
using namespace std;
class A {
      public:
      A();
      ~A();
};
A::A() {
      cout<<  "Constructing A\n";
}
A::~A() {
      cout<<  "Destructing A\n";
}
int main() {
      A a;
      A a2;
      A a3;
      A* ptr_a =&a;
      A* ptr_a2 =&a2;
      A* ptr_a3 =&a3;
      set<A*>  set_a;
      set_a.insert(ptr_a); set_a.insert(ptr_a2); set_a.insert(ptr_a3);
      set<A*>  set2_a;
      set2_a.insert(ptr_a); set2_a.insert(ptr_a2);
      cout<<  "Before erase\n";
      set_a.erase(set2_a.begin(), set2_a.end());
This is the line of error, see below.
      cout<<  "End of main\n";
      return 0;
}
--------------------------------------
The idea is that set_a should contain only ptr_a3 after the "erase"
operation. Instead, what I get is:
Constructing A
Constructing A
Constructing A
Before erase
Segmentation fault
What am I missing? According to the STL documentation for "set",
applying "erase" to an iterator-delimited range should be a valid
operation.
The incorrect assumption here is that you could provide *any* range as
argument of erase. This is not the case, it must be an iterator range of
the *same* container. This becomes clear, if you track the definition of
q1 and q2 from Table 69?"Associative container requirements (in addition
to container)" from the C++03 standard for the signature a.erase(q1,q2):
"In Table 69, X is an associative container class, a is a value of X
[..], [q1, q2) is a valid range in a, [..]"
Arguably one could also interpret the signature (without the explanatory
text) to erase all elements with the same *key* as the provided
sequence. A simple way to realize what you want is to take advantage of
the erase overload of set that takes a *key*:
for (set<A*>::const_iterator it = set2_a.begin(), end = set2_a.end(); it
!= end; ++it) {
   set_a.erase(*it);
}
In C++0x you *really* want to take advantage of the new for-range loop:
for (const auto& key : set2_a) {
   set_a.erase(key);
}
HTH & Greetings from Bremen,
Daniel Kr?gler
-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]