如何避免对地图访问进行常量转换?

How to avoid const cast for map access?

我有以下问题:

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 转换是一个设计问题,但如果我不想map中创建键,我不知道如何规避它const.

感谢任何帮助。

这里有两种可能的情况:

  1. obj 的函数 knows/expects 已经存在于地图中,为了方便起见,您正在使用 []

  2. 您正在使用 [] 以发挥其全部潜力,即您希望它将 obj 添加到地图(如果尚未存在)。

在情况 2 中,您的 getColor 签名有误。由于它可能会将 obj 传递到将其存储为 A* 的位置,因此仅接受 const A* 是错误的。请注意,即使函数不修改对象 本身 而是将其传递到可以修改的地方,它实际上是在间接修改它,因此应该将其视为非 const.

情况一,取决于你的C++版本。 C++14 引入了 template overload of findstd::map 的相关成员函数,它采用 任何与 Key 相当的东西,而不仅仅是 Key。因此,您可以像这样修改函数:

void getColor( A const * obj){
    doubel d = map.find(obj)->second;
    // do something
}

请注意,要使其正常工作,您还需要更改地图类型以使用透明比较器:std::map<A*,double, std::less<>> map;(正如 最先指出的那样)。

如果您坚持使用 C++11 或更早版本,那您就倒霉了,您将不得不忍受 const_cast。请注意,通过适当的注释,const_cast 在这种情况下是完全安全和可接受的(更不用说不更改 map 类型的唯一方法)。同样,您应该使用 find 或者 at 而不是 [],因为您不想插入到地图中。

如果您负担得起切换到 C++14,那么您可以配置您的映射以使用 transparent comparator(这将起作用,因为可以将 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
}

请注意,您必须使用 std::map::find() 而不是 std::map::operator[],因为后者 .