简体   繁体   English

C++ std::set::erase 与 std::remove_if

[英]C++ std::set::erase with std::remove_if

This code has the Visual Studio error C3892 .此代码具有 Visual Studio error C3892 If I change std::set to std::vector - it works.如果我将std::set更改为std::vector - 它可以工作。

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

What's wrong?怎么了? Why can't I use std::remove_if with std::set ?为什么我不能将std::remove_ifstd::set

You cannot use std::remove_if() with sequences which have const parts.您不能将std::remove_if()与具有const部分的序列一起使用。 The sequence of std::set<T> elements are made up of T const objects. std::set<T>元素序列由T const对象组成。 We actually discussed this question just yesterday at the standard C++ committee and there is some support to create algorithms dealing specifically with the erase() ing objects from containers.我们实际上就在昨天在标准 C++ 委员会上讨论了这个问题,并且有一些支持创建专门处理容器中的erase()对象的算法。 It would look something like this (see also N4009 ):它看起来像这样(另见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;
        }
    }
}

(it would probably actually delegate to an algorithm dispatching to the logic above as the same logic is the same for other node-based container). (它可能实际上委托一个算法调度到上面的逻辑,因为相同的逻辑对于其他基于节点的容器是相同的)。

For you specific use, you can use对于您的特定用途,您可以使用

a.erase(10);

but this only works if you want to remove a key while the algorithm above works with arbitrary predicates.但这仅适用于您想删除键而上述算法适用于任意谓词的情况。 On the other hand, a.erase(10) can take advantage of std::set<int> 's structure and will be O(log N) while the algorithm is O(N) (with N == s.size() ).另一方面, a.erase(10)可以利用std::set<int>的结构并且将是 O(log N) 而算法是 O(N) (其​​中N == s.size() )。

std::remove_if re-orders elements, so it cannot be used with std::set . std::remove_if重新std::remove_if元素,因此它不能与std::set一起使用。 But you can use std::set::erase :但是你可以使用std::set::erase

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

Starting with C++20, you can use std::erase_if for containers with an erase() method, just as Kühl explained.从 C++20 开始,您可以将std::erase_if用于具有erase()方法的容器,正如Kühl 所解释的那样。 Notice that this also includes std::vector , as it has an erase method.请注意,这也包括std::vector ,因为它具有擦除方法。 No more chaining a.erase(std::remove_if(... :)不再链接a.erase(std::remove_if(... :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM