That's right. Iterators in std::sets are constant (std::set::iterator and std::set::const_iterator are the same type). Hence, you are not allowed to change them directly. It's a bit awkward, but IIRC the standard decided to do this so people don't accidently change values in maps and sets which could disturb the sorting order. (In my own opinion a wrong decission, but that's another topic ;)
There are basically three solutions for this. mutable, const_cast and reinserting the value:
The mutable - approach looks like this:
1 2 3 4 5 6 7 8
|
// for the "mutable" - way, define the otherfield's mutable in your class.
// This way they are always changeable - regardless of const. Beware that this also means,
// they can be changed when you use const in other cases (e.g. to pass values to functions)
struct myClass {
...
mutable int otherfields1;
mutable int otherfields2;
};
|
If you just want to set the value once and don't want to open up the otherfields for
all places where you could use myClass in a const-matter, you can use const_cast.
|
const_cast<myClass&>(*it).otherfields1 = 100; // should work in allmost all environments just fine
|
Beware, however that const_cast can fail horribly, if the object you cast is really const (was declared as const). The std::set-implementations I know of don't do this, but if you run into trouble, this is a spot to look at. ;). Just don't use const_cast carelessly.
The last solution is considered by many the "cleanest" way: delete the object from the set, change it and then reinserting it back. It's unfortunately also inefficient. Attention: You
HAVE to use this way if you change anything that could affect the sorting order of the set! (in your case: key1 or key2)
1 2 3 4
|
...
myClass tmp = *myClass_set.erase(it);
tmp.otherfields1 = 100;
myClass_set.insert(tmp);
|
Ciao, Imi.