2014-06-17 145 views
2

此代码具有Visual Studio error C3892。如果我将std::set更改为std::vector - 它可以工作。C++ std :: set ::使用std :: remove_if擦除::

std::set<int> a; 
a.erase(std::remove_if(a.begin(), a.end(), [](int item) 
{ 
    return item == 10; 
}), a.end()); 

怎么了?为什么我不能使用std::remove_ifstd::set

+0

可能的重复[擦除删除成语与std ::设置失败与constness相关的错误](http://stackoverflow.com/questions/3792600/erase-remove-idiom-with-stdset-failing-with- constness-related-error) – legends2k

回答

7

不能与具有const部分序列使用std::remove_if()std::set<T>元素的序列由T const对象组成。实际上,我们昨天在标准C++委员会讨论了这个问题,并且有一些支持来创建专门处理来自容器的ing对象的算法。它会是这个样子(也N4009见):

template <class T, class Comp, class Alloc, class Predicate> 
void discard_if(std::set<T, Comp, Alloc>& c, Predicate pred) { 
    for (auto it{c.begin()}, end{c.end()}; it != end;) { 
     if (pred(*it)) { 
      it = c.erase(it); 
     } 
     else { 
      ++it; 
     } 
    } 
} 

(它可能实际上是委托给一个算法调度,以上述逻辑作为相同的逻辑是其他基于节点的容器相同)。

为您具体的使用,你可以,如果你想删除,而上述任意谓词作品算法的密钥使用

a.erase(10); 

但这只是作品。另一方面,a.erase(10)可以利用std::set<int>的结构,并将O(logN),而算法是O(N)(与N == s.size())。

2

std::remove_if重新排列元素,所以它不能与std::set一起使用。但是你可以使用std::set::erase

std::set<int> a; 
a.erase(10); 
+0

好的,谢谢。但。这是个问题吗?让它重新排序。由于复杂性? – herolover

+0

@herolover'std :: set'是有序的,并且它的对数查找需要排序(它是二叉查找树)。所以它与复杂性有关。 – juanchopanza

+1

@herolover'std :: set'元素的顺序是由比较函数预先确定的,你不能改变顺序,容器不能工作 – Erbureth