我有一个boost::multi_index
和一个hashed_non_unique
视图。我想完成的是,鉴于该视图中的关键,请使用
pair<myIter, myIter> iterRange = myView.equal_range(key);
for (myIter iter = iterRange.first; iter != iterRange.second; ++iter) {
// ...
}
查找与该键关联的所有元素。然后,通过过滤器运行这些元素
bool filter(Element e) { /* some filtering logic*/ }
并使用修饰符修改过滤结果
void modifier(Element e) { /* modify the elements with e.g. myView.modify() */ }
但是,仅将这些部分放在一起是行不通的,因为修改元素会导致multi_index的重新排序,这使我的iterRange无效。
正确的方法是什么?谢谢!
答案 0 :(得分:1)
对您提出的解决方案的一些评论:
BMIter
并不特殊,而仅仅是与容器的第一个索引关联的迭代器。请注意,当myIter
恰好是该第一个索引时,它将与myView
相同。iters
定义为vector<myIter>
并直接存储迭代器,而无需任何进一步的转换-您仍将达到预期的效果,即不受修改后潜在重新排序的影响。iterRange.second
之前)跳转。有了这个想法,您可以省下iters
的窍门,如下所示:
for (myIter iter = iterRange.first; iter != iterRange.second; ) {
auto nextIter = std::next(iter);
if (filter(*iter)) {
myView.modify(iter, modifier);
if (nextIter != iterRange.second && std::next(iter) == iterRange.second)
iterRange.second = iter;
}
iter = nextIter;
}
答案 1 :(得分:0)
我想我自己找到了答案。我们需要先缓存元素,然后再修改它们,以免改变顺序,而不是简单地修改for循环内的元素。这里的技巧是,不是将迭代器缓存到该特定视图,而是将迭代器缓存到元素本身,即
vector<BMIIter> iters;
for (myIter iter = iterRange.first; iter != iterRange.second; ++iter) {
if (filter(*iter)) {
iters.push_back(myBMI.iterator_to(*iter));
}
}
for (auto iter : iters) {
myBMI.modify(iter, modifier);
}
请注意,BMIIter
和myIter
是不同的迭代器类型-前者是元素本身的迭代器,而后者是myView特有的迭代器。修改multi_index中的元素会使后者无效,但是即使重新排序后,前者仍然保持有效。