给定 std::map 和指向键的非常量 class 的指针,如何通过指向 const 的指针访问它?

Given std::map with pointers to a non-constant class for keys, how to access it via a pointer to const?

有一个 std::map<A*, B*> m 类型的映射,它描述了类型 A 对象和类型 B 对象之间的对应关系。 有一个函数 int exctractInfo(const A *a) 需要从 B 类型的对象中读取一些信息,该类型的对象对应于 A 类型的给定对象。这是一个语义常量操作,不需要更改任何内容,我们只需要阅读一些信息,但问题是 C++ 不允许通过指向 const[ 的指针访问映射 m =45=].

考虑以下代码:

#include <map>

class A {

};

class B {
    int info_;

public:
    int info() const { return info_; }
};

std::map<A*, B*> m;

int exctractInfo(const A *a) {
    auto it = m.find(a);
    if (it != m.end() && it->second) {
       return it->second->info();
    }
    return -1;
}

int main () {
    return 0;
}

Here's a link 在线编译此代码。我收到以下错误:

error: invalid conversion from 'const A*' to 'std::map::key_type {aka A*}' [-fpermissive]

现在我看到两个解决方案:

  1. 重写类型std::map<A*, B*>std::map<const A*, B*>,因为我有源代码,但那基本上是一个库对象的类型,还有很多代码依赖它,所以它必须改变,因此改变地图类型是不可取的;

  2. 像这样使用 const cast:auto it = m.find(const_cast<A*>(a));,这似乎也不是一个好的解决方案,更多的是 hack。

我不明白为什么它不起作用。例如,如果密钥是 std::stringint,我可以通过 const std::string 访问 std::map<std::string, B*> 就好了。那么我的例子有什么问题呢?有没有合适的方法来处理这种情况?

I don't understand why it doesn't work. If the key is std::string or int, for example, I can access std::map via const std::string just fine. So what's wrong with my example?

因为指向非常量数据的常量指针和指向常量数据的非常量指针之间存在显着差异。您的地图以第一为关键,您尝试通过第二个。因此,如果您是 C++14 之前的版本,恐怕唯一可行的解​​决方案是 const_cast(当然除了更改密钥类型之外)。如果您可以使用 C++14 或更高版本,则 "transparent comparison" 可用,如 std::map::find() example 中所述。为了让它工作,你需要像这样声明你的地图:

std::map<A*, B*,std::less<>> m;

live example