我的情况类似于此主题中描述的情况:Getting around Boost Multi-Index container's constant elemets。简而言之,我有boost multi index container持有这样的结构:
struct Data {
Controller controller;
const int indexed_data;
}
我的索引数据永远不会改变,但控制器会这样做。所以,我的第一种方法是在modify电话中完成我需要的所有工作:
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实际调用控制器上的方法的最佳方法,或者我应该遵循thread beforementioned的建议并声明我的控制器mutable
?后者对我来说看起来很危险,因为人们可以通过声明任何mutable
来轻松搞砸索引,但正如我刚才所说,安全的做法事实证明毕竟不是那么安全。
答案 0 :(得分:2)
你提出这个问题是值得注意的,因为$folders = @('A', 'B')
$source = 'source'
$destination = 'destination'
$filter = '*.bak'
$folders | foreach {
$source_path = [io.path]::combine($source, $_)
$destination_path = [io.path]::combine($destination, $_)
gci $source_path -File -Filter $filter | sort -Property LastWriteTime -Descending |
Select -first 1 | copy -Destination $destination_path
}
的行为在Jon Kalb pointed my attention to a closely related problem in 2016之前一直保持稳定12年以上。
简而言之,modify
期望用户提供的修饰符不会抛出,除非它不会更改元素的键,在这种情况下会发生未定义的行为,如您所发现的那样。文档说的是(斜体矿):
例外安全:基本。如果某些用户提供的操作(可能
modify
除外)引发异常,则mod
指向的元素将被删除。
这是一个错误还是一个设计缺陷是有争议的,但无论如何我最近改变了实现,以便your use case will now result in the element being erased。这个更新的行为将在即将发布的Boost 1.66版本(2017年12月)中提供,届时文档将为:
例外安全:基本。如果某些用户提供的操作(包括
position
)引发异常,则mod
指向的元素将被删除。
与此同时,你需要保护修改器免受修改后的抛出 - 对此有所了解。如果您迫切需要新的position
行为,可以下载Boost.MultiIndex源代码并修补本地Boost安装。