map,lambda,remove_if [英] map, lambda, remove_if

查看:138
本文介绍了map,lambda,remove_if的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以,我有std :: map,lambda和stl算法(remove_if)的问题。实际上,与std :: list或std :: vector的代码相同。

So, i've problem with std::map, lambda and stl algorithm(remove_if). Actually, same code with std::list or std::vector works well.

我的测试示例:

#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’

我不明白这里有什么问题。所以,我很乐意阅读一些建议/指示。我的目标 - 使用新的lambda风格与std ::地图和算法,如remove_if。

I don't understand what's wrong here. So, i gladly to read some advices/directions about it. My goal - use new lambda-style with std::map and algorithms, such as remove_if.

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

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

推荐答案

问题是 std :: map< K,V> :: value_type std :: pair< const K,V& c $ c>,aka .first const 且不可分配。 Lambdas与这里的问题无关。

The problem is that std::map<K,V>::value_type is std::pair<const K, V>, aka .first is const and not assignable. Lambdas have nothing to do with the problem here.

std :: remove_if 通过移动容器的元素来移除项目,使得不符合谓词的所有内容都在前面,在返回之前迭代器。在迭代器之后的所有内容都是未指定的。它使用简单的赋值,因为你不能分配到一个 const 变量,你会得到这个错误。

std::remove_if "removes" items by moving the elements of the container around, so that everything that does not fit the predicate is at the front, before the returned iterator. Everything after that iterator is unspecified. It does that with simple assignment, and since you can't assign to a const variable, you get that error.

名称 remove 可能有点误导,在这种情况下,你真的想要 erase_if ,但唉,不存在。您必须重复所有项目,并使用 手动删除所有项目, map.erase(iterator)

The name remove can be a bit misleading and in this case, you really want erase_if, but alas, that doesn't exist. You'll have to make do with iterating over all items and erasing them by hand with 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循环头本身的迭代器,因为这将跳过一个元素的情况下,你擦除一个节点。

This is safe because you can erase individual nodes in the tree without the other iterators getting invalidated. Note that I did not increment the iterator in the for loop header itself, since that would skip an element in the case where you erase a node.

†现在,您应该注意到这会在 std :: map 的排序中造成严重破坏,这就是为什么键是 const - 因此,在插入项目后,您不能以任何方式影响排序。

† By now, you should have noticed that this would wreak havoc in the std::map's ordering, which is the reason why the key is const - so you can't influence the ordering in any way after an item has been inserted.

这篇关于map,lambda,remove_if的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆