An object in a set must be comparable with other objects in the set,
typically with its inbuilt operator< but perhaps with another predicate.
This comparison must be stable, transitive and various other rules
that I'm sure everyone knows.
We've taken the view that we can do anything we like to the objects in
the set *provided that what we do does nothing to alter the way it
sorts*. It looks as though this wasn't correct - that we can't do
anything at all that requires non-const behaviour on the object. In
fact it looks as though set's iterator is almost identical to its
const_iterator, so what we'll have to do is pull the object out of the
set, copy it, fiddle with the copy, then put the copy back. This sounds
Have I understood this correctly?
You have understood this correctly yes, however there are other options to
the remove/mutate/reinsert option, take a look at:
Yup. I had the exact same problem recently. By
[lib.associative.reqmts] point 5: Keys in an associative
container are immutable.
And in a set, the value is also the key.
That's why we have std::map: It's like a set, but with a mutable part on
each "key". It's what you should use when you want to change a part of the
key which isn't used to determine its ordering.
If you really, really, REALLY know what you are doing, you can beat
the compiler with a const_cast. The slightest mistake, and you are
toast, of course...
Thanks for the link. It explains everything - and it's silly.
If I want to break set I can very easily. I just have a const reference
in my set members to an external data item which is part of the key -
then change the data item through some other non-const reference.
So making iterator const has not cured the problem they were trying to
But it has caused this new problem that you have to take the item out of
the set (copy construct) modify the copy, then put it back (another copy
As I went back through the posts to forward them to my work account (no
NNTP) it occurred to me - Are you guys related :P
> Bo Persson wrote:
>> Yes. :-)
>> If you really, really, REALLY know what you are doing, you can beat the
>> compiler with a const_cast. The slightest mistake, and you are toast,
>> of course...
> Thanks for the link. It explains everything - and it's silly.
> If I want to break set I can very easily. I just have a const
> reference in my set members to an external data item which is part of
> the key - then change the data item through some other non-const
> So making iterator const has not cured the problem they were trying to avoid.
There is no way of preventing users from writing perverse code to
deliberately break invariants. The change makes it harder to do this
The near name reversal is indicative of the fact that one of us is
from a parallel universe and has a goatee.
You don't get to know which one.
I would say that's why we have boost::multi_index_container and
boost::intrusive containers. std::map it seems to me speaks
with a forked tongue, pair<key, value>. Although it takes a
little more effort, using an alternative to map avoids the
useless "first" and "second" terminology required by maps.
You can get by with maps in small programs, but how things
are named is more important in larger programs. I think
that some projects start out using maps and although they
would benefit from switching to an alternative, they lack
the resources to go back and rework things.