ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

c – map,lambda,remove_if

2019-09-29 00:17:03  阅读:208  来源: 互联网

标签:stl-algorithm c c11 lambda stdmap


所以,我对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_type是std :: pair< const K,V>,又名.first是const而不是可赋值的. Lambda与这里的问题无关.

std::remove_if通过移动容器的元素来“移除”项目,以便在返回的迭代器之前,不适合谓词的所有内容都位于前面.在迭代器之后的所有内容都未指定.它通过简单的赋值来实现,并且由于无法分配给const变量,因此会出现该错误.†

名称删除可能有点误导,在这种情况下,你真的想要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的顺序造成严重破坏,这就是密钥为const的原因 – 因此在插入项目后您无法以任何方式影响排序.

标签:stl-algorithm,c,c11,lambda,stdmap
来源: https://codeday.me/bug/20190928/1829753.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有