Laura
Laura

Reputation: 43

How to remove an element from a set within a map?

I have trouble removing an element from a set within a map called accesrightsByRank. The keys of the maps are different ACCESRIGHTs : owner, modify, read and none. The values of the map are sets with names of accessors with certain ACCESRIGHTs.

    map<ACCESSRIGHT, set<string>>::const_iterator i;
    set<string>::const_iterator j;

    for(i = this->accessrightsByRank.begin(); i != this->accessrightsByRank.end(); i++){
        for(j = (*i).second.begin(); j != (*i).second.end(); j++){
            if( (*j).compare(p_Username) == 0){
                i->second.erase(j);
            }
        }
    }

I thought i->second would give me the set from which I could erase the username who no longer has a certain ACCESRIGHT, but it seems I did something wrong. Could someone explain to me why this doesn't work and how I should adjust my code?

This is the error I receive:

IntelliSense: no instance of overloaded function "std::set<_Kty, _Pr, _Alloc>::erase [with _Kty=std::string, _Pr=std::less<std::string>, _Alloc=std::allocator<std::string>]" matches the argument list and object (the object has type qualifiers that prevent a match) argument types are: (std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<std::string>>>) object type is: const std::set<std::string, std::less<std::string>, std::allocator<std::string>>

Upvotes: 4

Views: 1016

Answers (2)

BartoszKP
BartoszKP

Reputation: 35891

As indicated by Piotr Skotnicki in his comment, you are using a const_iterator. The name alone indicates that such iterator does not permit changing the thing it's pointing to. Change these lines:

map<ACCESSRIGHT, set<string>>::const_iterator i;
set<string>::const_iterator j;

to this:

map<ACCESSRIGHT, set<string>>::iterator i;
set<string>::iterator j;

for the quickest fix. However after this, do consider all the advices from the comments under the question.

Upvotes: 3

timrau
timrau

Reputation: 23058

To summarize all the comments,

  1. You are modifying the map and the set. Thus you should use iterator, not const_iterator.
  2. To erase some value in a set, you don't need linear search. std::set::erase() has a variant that takes the value to be deleted.
  3. i->second is equivalent to and easier to read than (*i).second.
  4. this-> is redundant except if you have a local variable with the same name.

Combine them, you will get

map<ACCESSRIGHT, set<string>>::iterator i;

for(i = accessrightsByRank.begin(); i != accessrightsByRank.end(); i++){
    i->second.erase(p_Username);
}

Upvotes: 3

Related Questions