C++ map access discards qualifiers (const)

The following code says that passing the map as const into the operator[] method discards qualifiers:

#include <iostream>
#include <map>
#include <string>

using namespace std;

class MapWrapper {
public:
    const int &get_value(const int &key) const {
        return _map[key];
    }

private:
    map<int, int> _map;
};

int main() {
    MapWrapper mw;
    cout << mw.get_value(42) << endl;
    return 0;
}

Is this because of the possible allocation that occurs on the map access? Can no functions with map accesses be declared const?

MapWrapper.cpp:10: error: passing const std::map<int, int, std::less<int>,
std::allocator<std::pair<const int, int> > > as this argument of 
_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) 
[with _Key = int, _Tp = int, _Compare = std::less<int>, 
_Alloc = std::allocator<std::pair<const int, int> >] discards qualifiers

std::map's operator [] is not declared as const, and cannot be due to its behavior:

T& operator[] (const Key& key)

Returns a reference to the value that is mapped to a key equivalent to key, performing insertion if such key does not already exist.

As a result, your function cannot be declared const, and use the map's operator[].

std::map's find() function allows you to look up a key without modifying the map.

find() returns an iterator, or const_iterator to an std::pair containing both the key (.first) and the value (.second).

In C++11, you could also use at() for std::map. If element doesn't exist the function throws a std::out_of_range exception, in contrast to operator [].


Since operator[] does not have a const-qualified overload, it cannot be safely used in a const-qualified function. This is probably because the current overload was built with the goal of both returning and setting key values.

Instead, you can use:

VALUE = map.find(KEY)->second;

or, in C++11, you can use the at() operator:

VALUE = map.at(KEY);

You cannot use operator[] on a map that is const as that method is not const as it allows you to modify the map (you can assign to _map[key]). Try using the find method instead.


Some newer versions of the GCC headers (4.1 and 4.2 on my machine) have non-standard member functions map::at() which are declared const and throw std::out_of_range if the key is not in the map.

const mapped_type& at(const key_type& __k) const

From a reference in the function's comment, it appears that this has been suggested as a new member function in the standard library.