Why isn't the [] operator const for STL maps?

C++Constants

C++ Problem Overview


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?

C++ Solutions


Solution 1 - C++

For std::map and std::unordered_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://en.cppreference.com/w/cpp/container/map/operator_at

Solution 2 - C++

Now that with C++11 you can have a cleaner version by using at()

void MyClass::MyFunction( int x ) const
{
  std::cout << m_map.at(x) << std::endl;
}

Solution 3 - C++

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::vector

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
    }
}

Solution 4 - C++

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

Solution 5 - C++

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.

Solution 6 - C++

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRuncibleView Question on Stackoverflow
Solution 1 - C++AlanView Answer on Stackoverflow
Solution 2 - C++DeqingView Answer on Stackoverflow
Solution 3 - C++Martin YorkView Answer on Stackoverflow
Solution 4 - C++SatbirView Answer on Stackoverflow
Solution 5 - C++Nick BedfordView Answer on Stackoverflow
Solution 6 - C++Anthony CrampView Answer on Stackoverflow