Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ const std::map reference fails to compile

Is there a reason why passing a reference to a std::map as const causes the [] operator to break? I get this compiler error (gcc 4.2) when I use const:

error: no match for ‘operator[]’ in ‘map[name]’

Here's the function prototype:

void func(const char ch, std::string &str, const std::map<std::string, std::string> &map);

And, I should mention that there is no problem when I remove the const keyword in front of std::map.

If I've been instructed correctly, the [] operator will actually insert a new pair into the map if it doesn't find the key, which would of course explain why this happens, but I can't imagine that this would ever be acceptable behavior.

If there is a better method, like using find instead of [], I'd appreciate it. I can't seem to get find to work either though... I receive const mismatched iterator errors.

like image 375
Joe Bane Avatar asked Mar 26 '09 22:03

Joe Bane


4 Answers

Yes you can't use operator[]. Use find, but note it returns const_iterator instead of iterator:

std::map<std::string, std::string>::const_iterator it;
it = map.find(name);
if(it != map.end()) {
    std::string const& data = it->second;
    // ...
}

It's like with pointers. You can't assign int const* to int*. Likewise, you can't assign const_iterator to iterator.

like image 104
Johannes Schaub - litb Avatar answered Oct 22 '22 19:10

Johannes Schaub - litb


When you're using operator[], std::map looks for item with given key. If it does not find any, it creates it. Hence the problem with const.

Use find method and you'll be fine.

Can you please post code on how you're trying to use find() ? The right way would be :

if( map.find(name) != map.end() )
{
   //...
}
like image 33
Benoît Avatar answered Oct 22 '22 19:10

Benoît


If you're using C++11, std::map::at should work for you.

The reason std::map::operator[] doesn't work is that in the event of the key you're looking for not existing in the map, it will insert a new element using the provided key and return a reference to it (See the link for details). This is not possible on a const std::map.

The 'at' method, however, will throw an exception if the key doesn't exist. That being said, it is probably a good idea to check for the existence of the key using the std::map::find method before attempting to access the element using the 'at' method.

like image 4
Rohit Shrinath Avatar answered Oct 22 '22 19:10

Rohit Shrinath


Probably because there is no const operator[] in std::map. operator[] will add the element you're looking for if it doesn't find it. Therefore, use the find() method if you want to search without the possibility of adding.

like image 2
Fred Larson Avatar answered Oct 22 '22 19:10

Fred Larson