tags:

views:

462

answers:

6

Contrived example, for the sake of the question:

void MyClass::MyFunction( int x ) const
{
  std::cout << m_map[x] << std::endl
}

This won't compile, since the [] operator is non-const.

This is unfortunate, since the [] syntax looks very clean. Instead, I have to do something like this:

void MyClass::MyFunction( int x ) const
{
  MyMap iter = m_map.find(x);
  std::cout << iter->second << std::endl
}

This has always bugged me. Why is the [] operator non-const?

+1  A: 

Because sometimes you would like to do this:

void foo( std::vector<int> &bar )
{
    bar[4] += 19;
}
Crashworks
std::vector has two (overloaded) versions of operator[] for this purpose, one const and one non-const.
ChrisW
+1  A: 

An index operator should only be const for a read-only container (which doesn't really exist in STL per se).

Index operators aren't only used to look at values.

Nick Bedford
The question is, why doesn't it have two overloaded versions - one `const`, another non-`const` - as e.g. `std::vector` does.
Pavel Minaev
+8  A: 

Note for new readers.
The original question was about STL containers (not specifically about the std::map)

It should be noted there is a const version of operator [] on most containers.
It is just that std::map and std::set do not have a const version and this is a result of the underlying structure that implements them.

From std::vetor

reference       operator[](size_type n) 
const_reference operator[](size_type n) const

Also for your second example you should check for a failure to find the element.

void MyClass::MyFunction( int x ) const
{
    MyMap iter = m_map.find(x);
    if (iter != m_map.end())
    {
        std::cout << iter->second << std::endl
    }
}
Martin York
+14  A: 

For std::map, operator[] will insert the index value into the container if it didn't previously exist. It's a little unintuitive, but that's the way it is.

Since it must be allowed to fail and insert a default value, the operator can't be used on a const instance of the container.

http://www.cplusplus.com/reference/stl/map/operator%5B%5D/

Alan
`std::set` doesn't have `operator[]`.
avakar
Oops, that's right. Edited.
Alan
+1  A: 

If you declare your std::map member variable to be mutable

mutable std::map<...> m_map;

you can use the non-const member functions of std::map within your const member functions.

Anthony Cramp
This is a terrible idea, though.
GMan
Why is this a terrible idea?
Anthony Cramp
The API for your class lies if you do that. The function claims that it's const -- meaning that it won't modify any member variables -- but in reality it might be modifying the m_map data member.
Runcible
+1  A: 

Since operator[] might insert a new element into the container, it can't possibly be a const member function. Note that the definition of operator[] is extremely simple: m[k] is equivalent to (*((m.insert(value_type(k, data_type()))).first)).second. Strictly speaking, this member function is unnecessary: it exists only for convenience

sat