0

I get the following error message:

"expression must be a modifiable lvalue iter->first = iter->second;"

for the code:

func( const std::set<Edge> &obstructEdges1,
      const std::set<Edge> &obstructEdges2 )
{
std::set<Edge> obstructEdges = obstructEdges1;
obstructEdges.insert( obstructEdges2.begin(), obstructEdges2.end() );

for ( std::set<Edge>::iterator iter = obstructEdges.begin();
    iter != obstructEdges.end(); iter++ )
{
  if ( iter->first > iter->second )
  {
    int t = iter->first;
    iter->first = iter->second;
    iter->second = t;
  }
...

Edge is a pair of ints. What's wrong? Looks like iter->first is considered const for some reason.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
TT_ stands with Russia
  • 1,785
  • 3
  • 21
  • 33

2 Answers2

4

Yes, std::set iterator is always a const iterator even if the set itself is not const, i.e. std::set::iterator and std::set::const_iterator are both constant iterators (and can refer to the same type). Note that std::set is an associative container. In standard associative containers you are not allowed to modify the stored keys in place, which means that in std::set you are not allowed to modify anything at all. Of course, your comparator does not have to treat the entire set element as the key, but from the std::set point of view the whole thing is the key and is therefore immutable.

As it says in 23.2.4

6 iterator of an associative container is of the bidirectional iterator category. For associative containers where the value type is the same as the key type, both iterator and const_iterator are constant iterators. It is unspecified whether or not iterator and const_iterator are the same type.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
4

set<T>::iterator is always* a constant iterator, just like set<T>::const_iterator, so you can't use it to modify any elements of the set. If you could modify elements of the set directly, the set would most likely become unordered, which would just lead to Bad Things™.

* Well, since C++11, at least, though it's unlikely any major implementations ever had non-const set iterators before that for long anyway.

jwodder
  • 54,758
  • 12
  • 108
  • 124
  • I noticed yesterday that `set::begin()` returns a non-const iterator in VS2008. But then, VS2008 is ancient :) – R Sahu Aug 28 '14 at 21:00
  • I've used non-const `set` iterators in the past, and it's been very useful. You set up one part of the object as the key, which must be kept immutable, but you can modify the rest of the object at will. I'm sad to see that feature go away. – Mark Ransom Aug 28 '14 at 22:10