1

I have a profesor class with this atribute

vector<int> hDisponibles;

If I have a vector of this class

set<profesor> profesores;

I try this

set<profesor>::iterator itP;
itP = profesores.begin();    
while ( itP != profesores.end() ){                
    (*itP).hDisponibles->push_back(0);                                                    
    itP++;
}

but this errors

utils.cpp:138: error: passing ‘const std::vector<int, std::allocator<int> >’ as ‘this’     argument of ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = int, _Alloc = std::allocator<int>]’ discards qualifiers
JuanPablo
  • 23,792
  • 39
  • 118
  • 164

3 Answers3

4

std::set only offers const iterators, because modifying the objects while they're in the set would break set invariant. So, you can't do what you want with std::set, you need to either readd the new object, or use a different container.

Cat Plus Plus
  • 125,936
  • 27
  • 200
  • 224
3

Your problem is that the vector you are trying to call push_back on is const. This is because (since C++11) the elements of a std::set are accessed through const_iterators, since changing them might change how they compare and therefore corrupt the set. To solve that you have two options:

  1. If hDisponibles has no effect on how profesor compare and it doesn't do to much damage to your overall structure you can declare it mutable like this: mutable vector<int> hDisponibles;. mutable members can be changed even if the structure they reside in is const
  2. I that is not an option, you have to remove the profesor from the set (into a temporary), do your push_back and reinsert it (be careful about iterator invalidation). Of course this is quite costly.

Your code as posted has an additional bug, since hdisponsibles is an object, but push_back is called as if it was a pointer. From your compilermessage it doesn't seem like that bug is in your actual code, but just in case it should be:

(*itP).hDisponibles.push_back(0);    

Edit: Found the section in the standard draft (the value type is the same as the key for set and multiset: N3290 §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. [Note: iterator and const_iterator have identical semantics in this case, and iterator is convertible to const_iterator. Users can avoid violating the One Definition Rule by always using const_iterator in their function parameter lists. —endnote ]

Grizzly
  • 19,595
  • 4
  • 60
  • 78
  • Or instead of (2), you could rewrite the whole loop, so that you build a completely new set of the modified results. – Karl Knechtel Jan 03 '12 at 23:56
  • Alternatively, if hDisponibles were a pointer, then one wouldn't have to worry about the const/mutable stuff (as long as it isn't a pointer-to-const) – Sumudu Fernando Jan 04 '12 at 06:57
1

The obvious error with your code is that you're using -> instead of . on this line:

(*itP).hDisponibles->push_back(0);  // should be itP->hDisponibles.push_back(0);

But I have a feeling there are more errors related to syntax somewhere. Please post a more complete summary of the code and the errors you're getting.

Ron Warholic
  • 9,994
  • 31
  • 47
  • with (*itP).hDisponibles->push_back(0) error: base operand of ‘->’ has non-pointer type ‘const std::vector >’ – JuanPablo Jan 03 '12 at 22:31