I understand that calling a non-const method to a constant object gives an error as explained here. This question, although deals with the same error, is not a duplicate because it is not about a non-constant method.
This time I have a minimal reproducible example:
// Example program
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
class Something
{
public:
int m_value;
Something(): m_value{0} { myVector.push_back(1); myMap["hello"]=3; }
void setValue(int value) { m_value = value; }
int getValue() { return m_value ; }
//int getValue(const int value){ return myVector[value] ; } //<-- this gives an error (just reference)
int getValue(const int value)const { return myVector[value]; }
//int getValue2(const std::string &name) {return myMap[name]; } //<--- this gives an error (just reference)
int getValue2(const std::string &name) const {return myMap[name]; } //HERE this gives an error (this question)
std::vector<int> myVector;
std::unordered_map<std::string,int> myMap;
};
int main()
{
const Something something{}; // calls default constructor
int l= something.getValue(0);
std::cout<<l<<std::endl;
l= something.getValue2("hello"); //<-- HERE the error
std::cout<<l<<std::endl;
return 0;
}
In comments there are two method declarations that illustrates the point about non-constant methods. I left them there for reference. This question is not above them.
You see the const getValue
method that returns a vector element? This works without problem.
Now see the const getValue2
method that should return a unordered map element? Even though it is a constant method it generates an error
In member function 'int Something::getValue2(const string&) const':
17:68: error: passing 'const std::unordered_map<std::basic_string<char>, int>' as 'this' argument of 'std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type& std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::operator[](const key_type&) [with _Key = std::basic_string<char>; _Tp = int; _Hash = std::hash<std::basic_string<char> >; _Pred = std::equal_to<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, int> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::mapped_type = int; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_type = std::basic_string<char>]' discards qualifiers [-fpermissive]
My question is: Why only with unordered maps passing constant as the index generates this error?
EDIT: Thanks to the very useful answers. I modified the class to
// Example program
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
class Something
{
public:
int m_value;
Something(): m_value{0} { myVector.push_back(1); myMap["hello"]=3; }
void setValue(int value) { m_value = value; }
int getValue() { return m_value ; }
//int getValue(const int value){ return myVector[value] ; } //<-- this gives an error
int getValue(const int value)const { return myVector[value]; }
//int getValue2(const std::string &name) {return myMap[name]; } //<--- this gives an error
//this will generate an exception if name is not in the map
int getValue3(const std::string &name) const {
//return myMap[name];
return myMap.at(name);}
int getValue2(const std::string &name) const {
auto iter = myMap.find(name);
return (iter != myMap.end()) ? iter->second : 0;
}
std::vector<int> myVector;
std::unordered_map<std::string,int> myMap;
};