c++ - map , lambda ,remove_if

标签 c++ lambda c++11 stdmap stl-algorithm

所以,我对 std::map、lambda 和 STL 算法(remove_if)有疑问。实际上,与 std::list 或 std::vector 相同的代码效果很好。

我的测试示例:

#include <map>
#include <iostream>
#include <algorithm>

struct Foo
{
    Foo() : _id(0) {}
    Foo(int id) : _id(id)
    {

    }

    int _id;    
};
typedef std::map<int, Foo> FooMap;


int main()
{
    FooMap m;
    for (int i = 0; i < 10; ++i)
        m[i + 100] = Foo(i);

    int removeId = 6;
    // <<< Error here >>>
    std::remove_if(m.begin(), m.end(), [=](const FooMap::value_type & item) { return item.second._id == removeId ;} ); 

    for (auto & item : m )
        std::cout << item.first << " = " << item.second._id << "\n";    

    return 0;
}

错误信息:

In file included from /usr/include/c++/4.6/utility:71:0,
                 from /usr/include/c++/4.6/algorithm:61,
                 from main.cxx:1:
/usr/include/c++/4.6/bits/stl_pair.h: In member function ‘std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(std::pair<_T1, _T2>&&) [with _T1 = const int, _T2 = Foo, std::pair<_T1, _T2> = std::pair<const int, Foo>]’:
/usr/include/c++/4.6/bits/stl_algo.h:1149:13:   instantiated from ‘_FIter std::remove_if(_FIter, _FIter, _Predicate) [with _FIter = std::_Rb_tree_iterator<std::pair<const int, Foo> >, _Predicate = main()::<lambda(const value_type&)>]’
main.cxx:33:114:   instantiated from here
/usr/include/c++/4.6/bits/stl_pair.h:156:2: error: assignment of read-only member ‘std::pair<const int, Foo>::first’

我不明白这里有什么问题。所以,我很高兴阅读一些关于它的建议/指导。我的目标 - 使用带有 std::map 和算法的新 lambda 样式,例如 remove_if。

g++ 4.6,-std=c++0x。

最佳答案

问题是std::map<K,V>::value_typestd::pair<const K, V> ,又名 .firstconst并且不可分配。 Lambda 与这里的问题无关。

std::remove_if 通过移动容器的元素来“删除”项目,以便所有不符合谓词的内容都在前面,在返回的迭代器之前。该迭代器之后的所有内容都未指定。它通过简单的分配来做到这一点,因为你不能分配给 const变量,你会得到那个错误。

姓名remove可能有点误导,在这种情况下,你真的想要 erase_if ,但是很可惜,那不存在。您将不得不遍历所有项目并使用 map.erase(iterator) 手动删除它们。 :

for(auto it = map.begin(), ite = map.end(); it != ite;)
{
  if(it->second._id == remove_id)
    it = map.erase(it);
  else
    ++it;
}

这是安全的,因为您可以删除树中的单个节点,而不会使其他迭代器失效。请注意,我没有在 for 循环头本身中增加迭代器,因为在删除节点的情况下会跳过一个元素。


† 现在,您应该已经注意到这会对 std::map 造成严重破坏。的排序,这就是key为const的原因- 所以你不能在插入元素后以任何方式影响排序。

关于c++ - map , lambda ,remove_if,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9515357/

相关文章:

函数作为参数的 C++ 错误,对非常量的引用的初始值必须是左值

c++ - 在 union 内部使用 `initializer_list` ctor 进行结构化?

c++ - 让线程在自旋锁中休眠的方法

c++ - 对 avr 端口地址的 constexpr 引用

R 包中的 c++ 文档

c++ - 释放空指针会导致以下弹出消息

c++ - if 语句表达式调用函数,需要测试是否为真

c# - 访问已处置的闭包 - 将方法标记为安全

c++ - QtConcurrent::run with lambda on mac os 没有匹配函数

c++ - 由于在多个 cpps 中包含相同的 header 而导致重复的多个定义错误