1

Please watch this:

template<typename TK, typename TV>
class MetaAssociator
{
public:

   void Set(TK key, TV const & value)
   {
      boost::lock_guard<boost::mutex> lock(m_Mutex);
      m_Map[key] = value;
   }

   TV Get(TK key) const
   {
      boost::lock_guard<boost::mutex> lock(m_Mutex);
      std::map<TK,TV>::const_iterator iter = m_Map.find(key);
      return iter == m_Map.end() ? TV() : iter->second;
   }

private:
   mutable boost::mutex m_Mutex;
   std::map<TK,TV> m_Map;
};

When I change the std::map<TK,TV>::const_iterator iter to std::map<TK,TV>::iterator it is causing the following compile error:

error C2440: 'initializing' : cannot convert from stlpd_std::priv::_DBG_iter<_Container,_Traits> to stlpd_std::priv::_DBG_iter<_Container,_Traits>

Can anyone exmplain why? I am not modifying the m_Map. Why the compiler is complaining??

2
  • "I am not modifying the m_Map" but you're calling a non-const function on a const object (it's const because you're in a const function) Commented Apr 9, 2018 at 14:05
  • "I am not modifying the m_Map." Yes, you are not because find gives you back a const_iterator. If it worked as you wish, then you would be able to change it. The object is kept safe against changes via type of the variable, not tracking the actual usage. Commented Apr 9, 2018 at 14:52

3 Answers 3

4

Your MetaAssociator::Get method is marked as const, hence the field m_Map is also const in this method. Now, std::map::find can only return a const_iterator if the map itself is const.

This makes sense - why would you return non-const iterators to a const collection?

Sign up to request clarification or add additional context in comments.

Comments

3

The "why" is fairly simple.

The const here:

TV Get(TK key) const
               ^^^^^

...means that this is a Mediator const *. That means you can't modify any of its contents, which is enforced through the type system by preventing you from assigning directly or obtaining a non-const reference, pointer, iterator, etc., to the content1.

The bad part is that the error message you're getting it, quite frankly terrible. I recognize it well as one MS VC++ used to generate on quite a regular basis. About the only "why" I can give here is that it simply did a poor job of reporting this type of error. About the only cure of which I'm aware is to use a different compiler. In this case, it's probably easiest to update to a newer version of MS VC++. The error messages in VC++ 2017 are much better.


  1. Though it is still possible to bypass this protection by (for example) obtaining a pointer or reference to const, then later casting away the const-ness. The compiler tries to protect you from mistakes, but if you actively bypass its protection with a cast, you're pretty much on your own.

Comments

1

Your function Get is defined as const which means that access to any local properties have to be constant. ::iterator isn't constant but ::const_iterator is.

Here is something I found with a quick google search that may help you understand. https://www.studytonight.com/cpp/const-keyword.php

Just use const_iterator and you'll be fine. The compiler doesn't care if you actually modify the value, it only checks wether or not the values are constant or not.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.