71

The declaration for the [] operator on a std::map is this:

T& operator[] ( const key_type& x );

Is there a reason it isn't this?

T& operator[] ( const key_type& x );
const T& operator[] const ( const key_type& x );

Because that would be incredibly useful any time you need to access a member map in a const method.

Calder
  • 2,219
  • 1
  • 20
  • 21

5 Answers5

87

As of C++11 there is std::map::at which offers const and non-const access.

In contrast to operator[] it will throw an std::out_of_range exception if the element is not in the map.

Stephan Dollberg
  • 32,985
  • 16
  • 81
  • 107
  • 5
    _that's_ a great addition. – xtofl Dec 16 '12 at 15:37
  • That's much better than writing foo.get(bar)->second, thanks! =) – Calder Dec 16 '12 at 15:52
  • 6
    @Calder foo.find(bar)->second (not 'get') is just broken, unless you already know foo has an entry with bar as key, since otherwise it returns a non-dereferenceable iterator... – boycy Dec 17 '12 at 08:58
80

operator[] in a map returns the value at the specified key or creates a new value-initialized element for that key if it's not already present, so it would be impossible.

If operator[] would have a const overload, adding the element wouldn't work.

That answers the question. Alternatives:

For C++03 - you can use iterators (these are const and non-const coupled with find). In C++11 you can use the at method.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
16

These answers are correct in that operator[] has semantics to add a key if it doesn't exist, but I'd like to add another perspective:

Notice how operator[] returns a T&. That is, it returns a reference to the value that is associated with key. But what if there is no key in the map? What should we return? There's no such thing as a "null-reference," and throwing an exception would be annoying.

This would be one good reason for no operator[] const. What would you return to the user if you couldn't add anything to the map (because the operator is const), but they are looking for an item that doesn't exist? A good solution to this problem is to not have the operator[] const.

Cornstalks
  • 37,137
  • 18
  • 79
  • 144
  • 2
    Good answer. Maybe std::map could have a const accessor if it would return an iterator instead of T&. But I guess that's what std::map::find() is for. It would also be bad performance-wise and not very intuitive. – vobject Dec 16 '12 at 22:14
  • Why not just have a `T null_` member in the map object and return const references to that? – Inverse Jan 09 '13 at 15:33
  • 1
    @Inverse: And how do you initialize `null_`? What if, for example, `T` is `int`? – Cornstalks Jan 09 '13 at 17:11
6

The (non-const) operator[] creates the key if it doesn't exist.

The const version of that operator, if it existed, would have to have different semantics, since it wouldn't be able to add a new key.

I am sure you would agree that having const and non-const overloads with significantly different semantics would be a can of worms. Therefore no const version is provided.

There is a const find() member though, so you can use that in your code.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
4

Because the semantics of operator[] are to add the key if it doesn't exist.

eduffy
  • 39,140
  • 13
  • 95
  • 92