修改Boost多索引项的非索引字段的最佳方法:modify vs mutable
Best way to modify non-indexed field of Boost Multi-Index item: modify vs mutable
我遇到了与本线程中描述的情况类似的情况:绕过Boost多索引容器';s常数。简而言之,我有一个boost多索引容器,其中包含这样的结构:
struct Data {
Controller controller;
const int indexed_data;
}
我的索引数据永远不会更改,但控制器会更改。所以,我的第一个方法是在修改调用中完成我需要的所有操作:
container.modify(it, [](auto& data) {
data.controller.nonConstFunction();
});
显然,这对我来说是有效的,但我正在进行一些测试,以了解当lambda内部抛出异常时(在我的情况下会发生这种情况)该方法的行为,我对结果感到惊讶:
struct employee {
int id;
std::string name;
}
typedef multi_index_container<
employee,
indexed_by<
ordered_unique<BOOST_MULTI_INDEX_MEMBER(employee,int,id)>>
>
> employee_set;
employee_set es;
es.insert(employee{0,"Joe"});
es.insert(employee{1,"Carl"});
es.insert(employee{2,"Robert"});
es.insert(employee{4,"John"});
try {
auto it = es.find(4); // John
es.modify(it, [](auto& employee) {
employee.id = 1; // Same ID of Carl, should be erased
throw std::runtime_error("test");
});
} catch (const std::runtime_error& err) {
// handle error...
}
在此之后,如果您打印容器中的内容,则会得到:
0 Joe
1 Carl
2 Robert
1 John
尽管没有抛出异常,只将员工的ID更改为已存在的ID,但会检测到对索引的命中,并删除正在修改的员工。
正如我所说,我不会对容器的密钥进行任何更改,但在发现这一点后,我很担心。这是图书馆的错误吗?是否存在其他可能导致索引无效状态的情况?除了手动删除/修改其中一个"无效"条目外,我也找不到将索引"重新处理"到有效状态的方法。
除此之外(回到我自己的情况),使用modify是在我的控制器上实际调用方法的最佳方法,还是应该遵循前面线程的建议并声明我的控制器mutable
?后者对我来说看起来很危险,因为通过声明任何mutable
都可以很容易地破坏索引,但正如我刚刚展示的那样,安全的方法最终被证明并不那么安全。
你提出这个问题很了不起,因为modify
的行为已经稳定了12年多,直到Jon Kalb在2016年将我的注意力指向一个密切相关的问题。
简而言之,modify
希望用户提供的修饰符不会抛出,除非它不更改元素的键,在这种情况下,会出现未定义的行为,正如您所发现的那样。文件是这么说的(我的斜体字):
异常安全:基本。如果某个用户提供的操作引发异常(可能不包括
mod
),则position
指向的元素将被擦除。
这是一个bug还是一个设计缺陷是有争议的,但无论如何,我最近更改了实现,因此您的用例现在将导致元素被删除。此更新行为将在即将发布的Boost 1.66(2017年12月)中提供,届时文档将显示:
异常安全:基本。如果某个用户提供的操作(包括
mod
)引发异常,则position
指向的元素将被擦除。
同时,你需要保护你的修改器不受修改后抛出的影响——很抱歉。如果您迫切需要新的modify
行为,您可以下载Boost.MultiIndex源代码并修补您的本地Boost安装。
- 从容器创建一系列索引的最惯用方法是什么?
- 有没有更好的方法可以使用特征/C++实现 matlab 的逻辑索引?
- 有没有一种简单的方法可以在C++中获取特定索引之后向量中的所有项目?
- std::map 索引运算符与插入方法的性能
- 在C++中从距离矩阵创建索引向量的最快方法
- C++:检查向量中的元素是否大于另一个具有相同索引的元素的有效方法?
- 获得给定向量的排列索引列表的最佳方法是什么?
- 有没有一种简单的方法可以忽略 c++ 中的索引错误
- 当数量小于初始化索引时确定数组中元素数的方法
- 向量索引在C 中不会包裹吗?什么是解决方法
- 修改Boost多索引项的非索引字段的最佳方法:modify vs mutable
- 将元素从一个向量复制到另一个向量的最有效方法,给定一个不被复制的索引列表
- 从 C++ 数组元素的指针获取索引的最快方法是什么
- 在运行时按索引访问 std::tuple 元素的最佳方法
- 构造一个数组的有效方法,该数组采用C++中另一个数组中具有给定索引的元素
- 模型中虚拟索引实现的替代方法
- C++11 在运行时不使用 switch 为元组编制索引的方法
- 如何使用获取用户索引并返回其名字的访问器方法
- 使用C++在两个排序数组中查找匹配值索引的最有效方法
- c++中线程安全索引运算符的正确方法