tags:

views:

4169

answers:

4

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

+7  A: 

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.

nrl
By the way of explanation: what should map's operator[] do if the key does not exist? If the map is non-const, the key is added with default-constructed value. If the map const, what can be returned by operator[]? There is no value at that key.
Arkadiy
+18  A: 

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

data_type& operator[] (const key_type& k)

Returns a reference to the object that is associated with a particular key. If the map does not already contain such an object, operator[] inserts the default object data_type().

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.

luke
+1  A: 

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.

Nathan Kitchen
A: 

First, you should not be using symbols beginning with _ because they are reserved to the compiler writer. It would be very easy for _map to be a syntax error on someone's compiler, and you would have no one to blame but yourself.

If you want to use an underscore, put it at the end, not the beginning. You probably made this mistake because you saw some Microsoft code doing it. Remember, they write their own compiler, so they may be able to get away with it. Even so, it's a bad idea.

the operator [] not only returns a reference, it actually creates the entry in the map. So you aren't just getting a mapping, if there is none, you are creating one. That's not what you intended.

Dov