c++ - 'operator[]' 的多个重载实例化为相同的签名
问题描述
我有一个Object
存储一些 s的列表Data
。一旦一个对象被添加到列表中,它将永远不会被删除。给定一些数据,我还想快速查找它来自哪个对象。
而不是遍历整个列表并检查每个对象,我想创建一个从数据到对象的映射。
#include <vector>
#include <map>
class Data {/*Stuff here*/};
struct Object {
Data d;
Object(Data d) : d(d) {}
};
class ObjectStorage {
std::vector<Object> objects;
std::map<Data&, Object&> reverse_lookup;
public:
void add_object(Data d) {
objects.emplace_back(d);
auto &obj = objects.back();
reverse_lookup.emplace(obj.d, obj);
}
};
int main() {
ObjectStorage S;
S.add_object(Data());
}
为了节省空间,我在地图中使用了参考。对象和数据已经存储在列表中,我知道它们永远不会被删除。
但是,尝试编译此程序时出现以下错误。
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/map:1024:18: error: multiple overloads of 'operator[]' instantiate to the same signature 'std::__1::map<Data &, Object &, std::__1::less<Data &>, std::__1::allocator<std::__1::pair<Data &, Object &> > >::mapped_type &(std::__1::map<Data &, Object &,
std::__1::less<Data &>, std::__1::allocator<std::__1::pair<Data &, Object &> > >::key_type &)'
mapped_type& operator[](key_type&& __k);
^
test.cpp:13:27: note: in instantiation of template class 'std::__1::map<Data &, Object &, std::__1::less<Data &>, std::__1::allocator<std::__1::pair<Data &, Object &> > >' requested here
std::map<Data&, Object&> reverse_lookup;
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/map:1022:18: note: previous declaration is here
mapped_type& operator[](const key_type& __k);
^
1 error generated.
错误的主要部分似乎是:
错误:'operator[]' 的多个重载实例化为相同的签名
解决方案
该错误源于在std::map
. 请参阅问题“为什么我不能std::map
在 C++ 中存储引用?” 有关原因的更多信息。
如果不是太贵,reverse_lookup
可以通过更改地图以存储副本
std::map<Data, Object> reverse_lookup;
并添加一个定义bool operator<(const Data& lhs, const Data& rhs)
以允许Data
用作键将解决问题。
如果复制Data
成本Object
太高,可以使用指针映射代替引用。但是,请注意指向数据的存储方式。在这种情况下,如果objects
向量增长超过其内部容量并调整大小,则所有指针都将变为无效。使用类似的东西std::list
不会在内存中移动数据应该可以防止这个问题。感谢Christophe在评论中指出这一点。
推荐阅读
- vba - 设置打印区域直到最后一行
- php - 使用 cURL 对不同主机上当前用户的 PHP NTLM 身份验证失败
- reactjs - 无法在本机反应中循环遍历图像数组
- c# - 椭圆的 AutomationProperty 自动化 ID
- android - 如何完全避免并发修改和 NoElementException - RealmList android
- python - Pandas:无法安全地将传递的 int32 用户 dtype 转换为 float64
- python - PyInstaller:可执行文件仅在命令行中运行
- oracle - oracle ddl 触发器:使用删除前创建备份表
- gtk - 在 GTK+3 中更改 GtkScale 槽颜色
- python - 在英语中使用 SpaCy 进行人名检测。寻找答案