我需要遍历class T的一些对象。
它们存储在std::set<std::unique_ptr<T>> tees中。
循环主体的主要用途是使用对象,但通过这样做,我还将了解某些对象何时不再需要并可以删除。
我使用基于范围的for循环来迭代unique_ptrs:
for (std::unique_ptr<T> & tee : tees)我知道我不能在循环(UB)中调用tees.erase(tee)。因此,我应该收集助手集合中需要删除的unique_ptr。问题:指针是唯一的,因此我不能将它们复制到助手集合中。
我可以在std::set<T*>中收集原始指针,但是如何在循环之后使用这些指针从tees集合中删除匹配的unique_ptr?此外,当我在这个问题中使用智能指针时,再次收集原始指针会感到错误。
我可以切换到shared_ptr,但是只有为了删除对象才能共享指针。感觉不对。
我可以从基于范围切换到其他方面,比如自己处理迭代器,并在删除条目之前获得下一个迭代器。但是回到C++11之前的技术也是不对的。
我可以转到std::remove_if。(编辑:实际上我做不到。在本问题下面和所接受的答案下面的评论中解释。)循环的身体会移动到unary_predicateλ中。但是循环的主要目的不是决定是否应该删除对象,而是使用它们,修改它们。
最小阻力的方法似乎是回到迭代器处理,这样我甚至不需要一个助手集合。但我不知道你能不能帮我一个C++11-ish (或14,17)的解决方案?
发布于 2018-08-28 16:51:06
我不认为你能找到比
for(auto it = container.begin(), it != container.end();)
{
//use *it here
if(needs_to_be_erased)
it = container.erase(it);
else
++it;
}由于std::set不提供对其元素的可变访问,任何类型的transform或remove都无法工作。您必须构建一个迭代器容器,然后在处理完集合之后,遍历每个迭代器的容器,调用每个迭代器的erase。
发布于 2018-08-28 16:57:25
我认为您可以将这些位置复制到一个新的数据结构中,并通过反向访问新的数据结构在另一个循环中删除这些项。
int counter =0;
vector<int> indices;
for (unique_ptr<T> & tee : tees)
{
if (bCondition)
indices.push_back(counter);
counter++;
}
reverse(indices.begin(), indices.end());
for (int i : indices)
tees.erase(tees.begin() + i);发布于 2018-08-28 18:47:23
不是一个确切的解决方案,但是如果你必须做很多事情,你可以为它做你自己的算法。我想这不是标准库中的原因,因为算法需要知道容器才能执行擦除。
所以你可以这样做:
template<typename Cont, typename Pred>
void erase_if(Cont& c, decltype(std::begin(c)) b, decltype(std::end(c)) e, Pred p)
{
while(b != e)
{
if(p(*b))
b = c.erase(b);
else
++b;
}
}
template<typename Cont, typename Pred>
void erase_if(Cont& c, Pred p)
{ erase_if(c, std::begin(c), std::end(c), p); }那就把它叫做:
erase_if(tees, [](std::unique_ptr<int> const& up){
// use up here...
return (*up) & 1; // erase if odd number
});或
erase_if(tees, std::begin(tees), std::end(tees), [](std::unique_ptr<int> const& up){
// use up here...
return (*up) & 1; // erase if odd number
});https://stackoverflow.com/questions/52062704
复制相似问题