为何boost::range::remove_erase_if无法作用于std::map?
解决boost::range::remove_erase_if作用于std::map时的编译错误
问题场景
尝试用boost::range::remove_erase_if移除std::map中键为1的元素时,代码如下:
std::map<int, int> m = { { 1, 2 }, { 3, 4 } }; boost::range::remove_erase_if( m, [](const auto& it) { return it.first == 1; });
编译时报错:
12>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.29.30133\include\xmemory(1986,1): error C2679: binary '=': no operator found which takes a right-hand operand of type 'std::pair<const int,int>' (or there is no acceptable conversion) 12>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.29.30133\include\utility(269,11): message : could be 'std::pair<const int,int> &std::pair<const int,int>::operator =(volatile const std::pair<const int,int> &)' 12>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.29.30133\include\xmemory(1986,1): message : while trying to match the argument list '(std::pair<const int,int>, std::pair<const int,int>)'
但同样的用法在std::vector上能正常工作:
std::vector<int> v = { 1, 2, 3, 4 }; boost::range::remove_erase_if( v, [](const auto& it) { return it == 1; });
执行后v的内容为{2, 3, 4}。
原因
boost::range::remove_erase_if底层是基于序列容器的remove-erase惯用法实现的:通过std::remove_if把要保留的元素移动到容器前端,再调用erase删除末尾的无效元素。这个过程需要元素支持赋值操作,但std::map的元素是std::pair<const int, int>——键是const类型,无法被赋值,因此触发编译错误。
而std::vector的元素是可修改的,能满足赋值要求,所以可以正常运行。
解决方案
方案一:直接使用std::map的erase方法手动遍历删除
这是C++标准库的原生写法,不需要依赖Boost:
std::map<int, int> m = {{1, 2}, {3, 4}}; for (auto it = m.begin(); it != m.end();) { if (it->first == 1) { it = m.erase(it); // erase返回下一个有效迭代器 } else { ++it; } }
方案二:使用Boost Range的erase_if函数(Boost 1.70+)
Boost为关联容器提供了专门的erase_if函数,直接遍历容器并删除符合条件的元素,避免了赋值操作:
std::map<int, int> m = {{1, 2}, {3, 4}}; boost::range::erase_if(m, [](const auto& pair) { return pair.first == 1; });
内容的提问来源于stack exchange,提问作者Dennix
相关产品推荐
相关产品推荐

