I have an accessor function that returns a const reference to a type (std::map) ... ...
myMap_t const& getMap() const {return paramMap;}
The type has an overloaded []
operator. What is the syntax to then use the []
operator directly from the getter function in a way like the following, but that actually works.
parameter = contextObj.getMap()[key];
Error message is:
context.cpp:35: error: passing
'const std::map<
std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
float,
std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >,
std::allocator<std::pair<
const std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
float> > >'
as 'this' argument of
'_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&)
with
_Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
_Tp = float,
_Compare = std::less<std::basic_string<char, std::char_traits<char>, td::allocator<char> > >,
_Alloc = std::allocator<std::pair<
const std::basic_string<char, std::char_traits<char>, std::allocator<char> >,
float> >]'
discards qualifiers
You return the
std::map
by const reference, butstd::map::operator[]
is not a const function, because sometimes it needs to alter the map.To solve this, you should do one of the following:
(A) Use
.find
instead of[]
(B) Return the map as non const (not recommended)
(C) Make a wrapper class (not worth it most of the time)
You return a
const myMap_t&
from your methodgetMap()
. From your error messagemyMap_t
is a typedef for astd::map
. Theroperator[]
ofstd::map
needs a modifiable object (can't be called on const), since it can insert items into the map (if no item with the specified key exists, it will insert one into the map and return a reference to that one). To solve that problem you have two options:contextObj.getMap().find(key)
instead ofcontextObj.getMap()[key]
to get an iterator to the element (or tomap.end()
if it doesn't exist)myMap_t&
(without const) to get a modifiable object on whichoperator[]
can be calledThe problem is that
operator[]
in a map is a mutating operation, and you cannot call it on a const reference to a map. The reason that it is mutating is that it must return a reference to a value, and for that, if the key was not already present in the container, it will insert a new default constructed value addressed by that key and return the reference to it.If you have a const reference, and you want to determine whether an element is present (or access it), you must use
std::map<>::find
that will return an iterator. If the element is not present the value of the iterator would bem.end()
std::basic_string
is the template used to implementstd::string
, and indeedstd::string
is simply the instantiation based onchar
. So substitute that in first:We don't really care about the
_Compare
(comparison function) and_Alloc
(allocator) arguments for our map, since we're just using the defaults; so let's ignore those, and let's also substitute the_Key
and_Tp
values into the template description:There we go, much simpler. We're using the
operator[]
of ourstd::map<std::string, float>
, and we're trying to use it on aconst std::map<std::string, float>
(i.e., that's what we're using as thethis
argument for the call). This "discards qualifiers", specifically, theconst
qualifier.The compiler is telling you that the
operator[]
of the map does not promise to keep the mapconst
, i.e. it is allowed to change the map. And that is a compiler error, because the code is written with the built-in assertion that the map won't change.Why would the map change? Well, look at the documentation:
(Emphasis mine).
Inserting an element is certainly a modification.
Why does it do this? Well, we already have a question for that.