我有这样的代码:
std::map<int, const Data> all_data;
// ...
bool OldDataIsBetter(Data const& oldData, Data const& newData) {...}
// ...
void AddData(int key, Data&& newData)
{
auto [it, ok] = all_data.try_emplace(key, std::move(newData));
if (!ok)
{
if (OldDataIsBetter(*it, newData)) return;
it->second = std::move(newData);
}
}
这不会编译,因为it->second
引用了const Data
,因此无法调用其赋值运算符。如果删除const
,它将正常工作。
上面的意图是insert_or_assign
,除了如果一项已经存在,那么我需要比较旧项目和新项目,以查看哪个项目“更好”。
使用const
声明地图元素类型的意图是,数据应该在地图中一次是不可变的-整个项目可以替换,但不能零星修改。
我可以“修复”以上通过重新分配到容器:
all_data[key] = std::move(newData);
(实际上是const
也有同样的问题。)
或通过擦除并重试位置:
all_data.erase(it);
all_data.emplace(key, std::move(newData)); // should never fail
但是这些都不是优雅的,因为我已经有了一个迭代器,该迭代器指向应替换的项目,并且以上两者都忘记了,然后再次进行搜索。
是否有更好的方法来完成此替换?
经过进一步的实验,我认为以下是当前可用于此方案的最佳方法:
it = all_data.erase(it);
all_data.emplace_hint(it, key, std::move(newData)); // should never fail
这对我来说仍然不理想,因为它仍然会重新分配地图节点。这不是世界的尽头,但我想找到一种避免这种情况的方法。