2016-08-12 59 views
7

我打算從對列表中刪除元素。當我用一對像std :: const中的常量參數:: remove_if

std::pair<const int, bool>

我得到以下編譯錯誤:

In file included from /usr/local/include/c++/6.1.0/utility:70:0,

from /usr/local/include/c++/6.1.0/algorithm:60,

from main.cpp:1:

/usr/local/include/c++/6.1.0/bits/stl_pair.h: In instantiation of 'std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(std::pair<_T1, _T2>&&) [with _T1 = const int; _T2 = bool]':

/usr/local/include/c++/6.1.0/bits/stl_algo.h:868:16: required from '_ForwardIterator std::__remove_if(_ForwardIterator, _ForwardIterator, _Predicate) [with _ForwardIterator = std::_List_iterator > _Predicate = __gnu_cxx::__ops::_Iter_pred&)> >]'

/usr/local/include/c++/6.1.0/bits/stl_algo.h:936:30: required from '_FIter std::remove_if(_FIter, _FIter, _Predicate) [with _FIter = std::_List_iterator > _Predicate = main()::&)>]'

main.cpp:17:32: required from here

/usr/local/include/c++/6.1.0/bits/stl_pair.h:319:8: error: assignment of read-only member 'std::pair::first'

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. 只要列表中的任何元素存在常量,我就會遇到完全相同的問題,例如,list <const int>也會返回編譯錯誤。

  2. 如果我刪除該對中第一個元素的常量,代碼將起作用。

  3. 的更加優雅和有效的方式做到這一點是使用的remove_if列表方法,像這樣:

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

,但我的問題是,什麼是完全性病的內部運作:: remove_if強制容器的元素不是const

+0

'std :: remove_if'要求解除引用的類型爲* MoveAssignable *,其中'std :: pair '不是。 – user657267

回答

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 s不能在const對象上完成。

5

通用std::remove_if對項目值進行混洗以將邏輯擦除值置於序列末尾(通常與成員函數erase結合使用以實際刪除邏輯擦除值)。當物品不可複製或移動時,不能進行洗牌。請使用std::list::remove_if

相關問題