std :: remove_if中的const参数

时间:2016-08-12 12:57:07

标签: c++ list c++11 lambda stl

我要从列表中删除元素。当我使用像

这样的一对时

std::pair<const int, bool>

我收到以下编译错误:

  

在/ usr / local / include / c ++ / 6.1.0 / utility:70:0中包含的文件中,

     

来自/ usr / local / include / c ++ / 6.1.0 / algorithm:60,

     

来自main.cpp:1:

     

/ usr / local / include / c ++ / 6.1.0 / bits / stl_pair.h:实例化   &#39; std :: pair&lt; _T1,_T2&gt;&amp; std :: pair&lt; _T1,_T2&gt; :: operator =(std :: pair&lt; _T1,   _T2&gt;&amp;&amp;)[with _T1 = const int; _T2 = bool]&#39;:

     

/ usr / local / include / c ++ / 6.1.0 / bits / stl_algo.h:868:16:从   &#39; _ForwardIterator std :: __ remove_if(_ForwardIterator,_ForwardIterator,   _Predicate)[与_ForwardIterator = std :: _ List_iterator&gt; _Predicate =   __gnu_cxx :: __ OPS :: _ Iter_pred&安培;)&GT; &GT;]&#39;

     

/ usr / local / include / c ++ / 6.1.0 / bits / stl_algo.h:936:30:从   &#39; _FIter std :: remove_if(_FIter,_FIter,_Predicate)[with _FIter =   std :: _ List_iterator&gt; _Predicate =   主()::&安培;)&GT;]&#39;

     

main.cpp:17:32:从这里要求

     

/ usr / local / include / c ++ / 6.1.0 / bits / stl_pair.h:319:8:错误:赋值   只读成员&#st; :: pair :: first&#39;

     

first = std :: forward(__ p.first);

这是示例代码:

int main()
{
    int id = 2;

    std::list< std::pair <const int, bool> >  l;
    l.push_back(std::make_pair(3,true));
    l.push_back(std::make_pair(2,false));
    l.push_back(std::make_pair(1,true));

    l.erase(std::remove_if(l.begin(), l.end(), 
        [id](std::pair<const int, bool>& e) -> bool {
        return e.first == id; }));

    for (auto i: l) {
        std::cout << i.first << " " << i.second << std::endl;
    }
}

我知道(如果我错了,请纠正我):

  1. 只要列表的任何元素中存在constness,我就会遇到完全相同的问题,例如,list <const int>也会返回编译错误。

  2. 如果删除对中第一个元素中的const,代码将起作用。

  3. 更优雅高效的方法是使用remove_if list方法,如下所示:

    l.remove_if([id](std::pair<const int, bool>& e) -> bool {
        return e.first == id; });
    
  4. 但我的问题是,std :: remove_if的内部工作原理是什么,它强加了容器的元素不是 const

2 个答案:

答案 0 :(得分:5)

一般std::remove_if随机播放项目值,将逻辑上删除的值放在序列的末尾(它通常与成员函数erase结合使用,以实际删除逻辑上删除的值值)。当物品不可复制或移动时,它不能进行改组。而是使用std::list::remove_if

答案 1 :(得分:4)

如果查看std::remove_if的类型和迭代器要求,可以看到实现必须类似于以下内容(来自上面的链接):

template<class ForwardIt, class UnaryPredicate>
ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPredicate p)
{
    first = std::find_if(first, last, p);
    if (first != last)
        for(ForwardIt i = first; ++i != last; )
            if (!p(*i))
                *first++ = std::move(*i);
    return first;
}

即,该算法仅假设迭代器具有前向能力,并且元素是可移动的,并且它是move个元素。当然,move无法在const个对象上完成。