Const arguments to std :: remove_if

I am going to remove items from a list of pairs . When I use a pair, for example

std::pair<const int, bool>

I get the following compilation error:

In the file included in / 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/++/6.1.0/bits/stl_pair.h: when creating 'std :: pair <_T1, _T2> & std :: pair <_T1, _T2> :: operator = (std: : pair <_T1, _T2> &) [with _T1 = const int; _T2 = bool] ':

/usr/local/include/++/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/++/6.1.0/bits/stl_algo.h: 936: 30: required from '_FIter std :: remove_if (_FIter, _FIter, _Predicate) [with _FIter = std :: _ List_iterator> _Predicate = Primary () :: &)>] '

main.cpp: 17: 32: required from here

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

first = std :: forward (__p.first);

This is a sample code:

 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; } } 

I know that (please correct me if I am wrong):

  • I will have exactly the same problem as long as there is a constant in any element of the list, for example, list <const int> will also return a compilation error.

  • If I remove const in the first element of the pair, the code will work.

  • A more elegant and efficient way to do this is to use the remove_if list method, for example:

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

but my question is what exactly are the internal actions of std :: remove_if that impose elements of a container not const?

+7
c ++ list lambda c ++ 11 stl
source share
2 answers

If you look at the requirements of the type and iterator std::remove_if , you will see that the implementation should look like the following (from the link above):

 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; } 

Ie, the algorithm assumes that iterators have capabilities ahead, and elements are movable, and move elements are around. Of course, move cannot be done on const objects.

+4
source share

The generic std::remove_if moves element values ​​around to put logically erased values ​​at the end of the sequence (usually used in combination with the erase member erase to actually remove logically erased values). It cannot be shuffled when an item cannot be copied or moved. Use std::list::remove_if .

+5
source share

All Articles