如何避免地图访问的常量投射?
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
的指针作为输入。
getColor
函数在不使用const_cast的情况下将无法编译。
const cast是一个设计问题,但是如果我不想在const中制作键map
我不知道如何规避它。
任何帮助表示赞赏。
这里有两种可能的情况:
-
该函数知道/期望地图中已存在
obj
,并且您使用[]
是为了方便起见。 -
您正在使用
[]
充分发挥其潜力,即您希望它在地图上添加obj
(如果还没有的话)。
在情况 2 中,getColor
签名中出现错误。由于它可以潜在地将obj
传递到存储为A*
的地方,因此它只接受const A*
是错误的。请注意,即使函数不修改对象本身,而是将其传递到可以修改的对象,它也实际上是间接修改它,因此应将其视为非const
。
在情况 1 中,这取决于您的C++版本。C++14 引入了find
的模板重载以及std::map
的相关成员函数,它采用与Key
相当的任何内容,而不仅仅是Key
。因此,您可以像这样修改函数:
void getColor( A const * obj){
doubel d = map.find(obj)->second;
// do something
}
请注意,要使其正常工作,您还需要更改地图的类型以使用透明比较器:std::map<A*,double, std::less<>> map;
(正如@Leon的答案首先指出的那样)。
如果您坚持使用 C++11 或更早,那么您就不走运了,您将不得不忍受const_cast
。请注意,通过适当的注释,在这种情况下,const_cast
是完全安全且可接受的(更不用说在不更改map
类型的情况下继续前进的唯一方法)。同样,您应该使用find
或at
而不是[]
,因为您不想插入到地图中。
如果您有能力切换到 C++14,那么您可以将映射配置为使用透明比较器(这将起作用,因为常量指针可以与非常量指针进行比较):
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[]
,因为后者没有透明版本。
- 是否应避免从非常量迭代器转换为常量迭代器?
- 避免在静态常量类上定义但不使用
- 如何避免使用 lambda 进行代码重复的常量和非常量集合处理
- 现代C++编译器是否能够避免在某些条件下两次调用常量函数
- 避免或警告在 GCC 中从常量字符* 隐式转换为布尔值
- 如何避免语法相同的常量和非常量函数之间代码重复,这些函数在语义上不相同
- 如何避免地图访问的常量投射?
- 避免Qt中的非符号常量
- 避免构造函数中常量引用和右值引用呈指数增长
- 如何避免内存泄漏与返回常量字符*
- 如何在模板中定义浮点常量.避免在运行时强制转换
- 可视化C++构造函数、常量、继承和避免重复
- 避免在用于区分常量和非常量模板函数中的代码重复
- 何时使用外部链接初始化全局常量,避免静态初始化顺序惨败
- C++ 移动构造函数和常量成员指针或常量成员,如何对它们进行 NULIZE 以避免内存泄漏
- 如何避免模板代码中编译时常量条件"conditional expression is constant"警告?
- float的类内静态常量初始化与C++中的int有何不同
- 我的常量和非常量链表迭代程序有何不同
- 避免重复 getter 的常量和非常量版本
- 如何避免在C++中从字符串常量到'char*'的已弃用转换