如何避免const转换为地图访问?

时间:2016-11-24 13:43:02

标签: c++ c++11 c++14 stdmap

我有以下问题:

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 中创建密钥,我不知道如何规避它强>

任何帮助表示感谢。

2 个答案:

答案 0 :(得分:19)

这里有两种可能的情况:

  1. 该函数知道/期望地图中已存在obj,并且您使用[]是为了方便。

  2. 您正在使用[]充分发挥其潜力,即如果尚未将obj添加到地图中,则您希望将getColor添加到地图中。

  3. 在情况2中,obj签名中存在错误。由于它可能会将A*传递到将其存储为const A*的位置,因此仅接受const是错误的。请注意,即使某个函数没有修改对象本身,但是将其传递到可以修改它的某个地方,它也会间接地对其进行修改,因此应该将其视为非std::map

    在情况1中,它取决于您的C ++版本。 C ++ 14引入了template overload of findKey的相关成员函数,它们使用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[]