I have the following issue:
std::map<A*,double> map;
void getColor(A const * obj){
double d = map[obj]; // does not compile wihtout const_cast<A*>(obj)
// do something
}
I have a map std::map
(somewhere) which stores pointers to objects A
.
I have a function getColor
which does not manipulate objects A
and so takes a pointer to a const A
as input.
The function getColor
will not compile without using a const_cast.
The const cast is a design issue, but I don't know how to circumvent it if I don't want to make the keys in map
const.
Any help appreciated.
There's two possible scenarios here:
The function knows/expects that obj
is already present in the map, and you're using []
for convenience.
You're using []
for its full potential, i.e. you expect it to add obj
to the map if not already there.
In situation 2, you have an error in the getColor
signature. Since it can potentially pass obj
to a place where it will be stored as A*
, it is wrong for it to accept a const A*
only. Note that even if a function doesn't modify an object itself but passes it on somewhere where it can be modified, it is effectively modifying it indirectly and should therefore take it as non-const
.
In situation 1, it depends on your C++ version. C++14 introduced a template overload of find
and related member functions of std::map
which takes anything comparable with Key
instead of only Key
. You could therefore modify the function like this:
void getColor( A const * obj){
doubel d = map.find(obj)->second;
// do something
}
Note that for this to work, you also need to change the map's type to use a transparent comparator: std::map<A*,double, std::less<>> map;
(as first pointed out by @Leon's answer).
If you're stuck with C++11 or earlier, you're out of luck and you'll have to live with the const_cast
. Note that with a suitable comment, a const_cast
is perfectly safe and acceptable in this case (not to mention the only way to proceed without changing the type of map
). Again, you should use find
or perhaps at
instead of []
, since you do not want to insert into the map.
If you can afford switching to C++14 then you can configure your map to use a transparent comparator (this will work since a const pointer can be compared with a non-const pointer):
std::map<A*,double, std::less<>> map;
// ^^^^^^^^^^^
// enable transparent comparator on this map
void getColor( A const * obj){
auto it = map.find(obj);
assert(it != map.end());
double d = it->second;
// do something
}
Note that you will have to use std::map::find()
instead of std::map::operator[]
, since the latter doesn't have a transparent version.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With