2016-08-12 4 views
7

のリストのリストから要素を削除します。私はstd :: remove_if内のconst引数

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. リストのどの要素にもconstanceがある限り、まったく同じ問題が発生します。例えば、list <const int>もコンパイルエラーを返します。

  2. ペアの最初の要素のconstを削除すると、コードが機能します。それを行うには

  3. よりエレガントかつ効率的な方法は、このように、remove_ifリスト方式を使用することです:

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

が、私の質問は正確にSTDの内部の仕組みどのようなものであり、::コンテナの要素がconstではないremove_if?

+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です。もちろんconstオブジェクトではmoveを実行することはできません。周り

5

一般std::remove_ifシャッフル項目値は、(一般的に、実際に論理的に消去値を削除するメンバ関数eraseと組み合わせて使用​​しています)シーケンスの最後に、論理的に消去値を置きます。それは、アイテムがコピー可能でも移動可能でもない場合、そのシャフリングを行うことはできません。代わりにstd::list::remove_ifを使用してください。

関連する問題