此代码包含Visual Studio error C3892
。如果我将std::set
更改为std::vector
- 就可以了。
std::set<int> a;
a.erase(std::remove_if(a.begin(), a.end(), [](int item)
{
return item == 10;
}), a.end());
出了什么问题?为什么我不能将std::remove_if
与std::set
一起使用?
答案 0 :(得分:13)
您不能将std::remove_if()
用于包含const
部分的序列。 std::set<T>
元素的序列由T const
个对象组成。我们昨天在标准的C ++委员会中实际上讨论了这个问题,并且有一些支持来创建专门处理来自容器的erase()
对象的算法。它看起来像这样(另见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(log N),而算法是O(N)(带N == s.size()
)。
答案 1 :(得分:4)
std::remove_if
重新排序元素,因此无法与std::set
一起使用。但您可以使用std::set::erase
:
std::set<int> a;
a.erase(10);
答案 2 :(得分:1)
从 C++20 开始,您可以将 std::erase_if 用于具有 erase()
方法的容器,正如 Kühl 解释的那样。
请注意,这也包括 std::vector
,因为它具有擦除方法。不再链接 a.erase(std::remove_if(...
:)