我有以下问题:
std::map<A*,double> map;
void getColor(A const * obj){
double d = map[obj]; // does not compile wihtout const_cast<A*>(obj)
// do something
}
我有一个地图std::map
(某处),它存储指向对象A
的指针。
我有一个函数getColor
不操纵对象A
,因此将const A
指针作为输入。
如果不使用const_cast,函数getColor
将无法编译。
const cast是一个设计问题,但如果我不希望在map
const >中创建密钥,我不知道如何规避它强>
任何帮助表示感谢。
答案 0 :(得分:19)
这里有两种可能的情况:
该函数知道/期望地图中已存在obj
,并且您使用[]
是为了方便。
您正在使用[]
充分发挥其潜力,即如果尚未将obj
添加到地图中,则您希望将getColor
添加到地图中。
在情况2中,obj
签名中存在错误。由于它可能会将A*
传递到将其存储为const A*
的位置,因此仅接受const
是错误的。请注意,即使某个函数没有修改对象本身,但是将其传递到可以修改它的某个地方,它也会间接地对其进行修改,因此应该将其视为非std::map
在情况1中,它取决于您的C ++版本。 C ++ 14引入了template overload of find
及Key
的相关成员函数,它们使用与Key
相比的任何内容,而不仅仅是void getColor( A const * obj){
doubel d = map.find(obj)->second;
// do something
}
。因此,您可以像这样修改函数:
std::map<A*,double, std::less<>> map;
请注意,要使其正常工作,您还需要更改地图的类型以使用透明比较器:const_cast
(由@Leon's answer首先指出)。
如果你坚持使用C ++ 11或更早版本,那么你运气不好,你将不得不忍受const_cast
。请注意,通过合适的评论,map
在这种情况下是完全安全且可接受的(更不用说在不更改find
类型的情况下继续进行的唯一方法)。同样,您应该使用at
或[]
代替spec
,因为您不想插入地图。
答案 1 :(得分:6)
如果你可以负担得起切换到C ++ 14那么你可以配置你的地图使用transparent comparator(这将起作用,因为const指针可以与非const指针进行比较):
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
}
请注意,由于后者doesn't have a transparent version,您必须使用std::map::find()
而不是std::map::operator[]
。