map, lambda, remove_if

后端 未结 2 1386
我寻月下人不归
我寻月下人不归 2020-12-09 18:36

So, i\'ve problem with std::map, lambda and stl algorithm(remove_if). Actually, same code with std::list or std::vector works well.

My test example :



        
相关标签:
2条回答
  • 2020-12-09 18:59

    You could use find and erase for the map. It's not as convenient as remove_if, but it might be the best you've got.

    int removeId = 6;
    auto foundIter = m.find(removeId);
    
    // if removeId is not found you will get an error when you try to erase m.end()
    if(foundIter != m.end())
    {
        m.erase(foundIter);
    }
    
    0 讨论(0)
  • 2020-12-09 19:04

    The problem is that std::map<K,V>::value_type is std::pair<const K, V>, aka .first is const and not assignable. Lambdas have nothing to do with the problem here.

    std::remove_if "removes" items by moving the elements of the container around, so that everything that does not fit the predicate is at the front, before the returned iterator. Everything after that iterator is unspecified. It does that with simple assignment, and since you can't assign to a const variable, you get that error.

    The name remove can be a bit misleading and in this case, you really want erase_if, but alas, that doesn't exist. You'll have to make do with iterating over all items and erasing them by hand with map.erase(iterator):

    for(auto it = map.begin(), ite = map.end(); it != ite;)
    {
      if(it->second._id == remove_id)
        it = map.erase(it);
      else
        ++it;
    }
    

    This is safe because you can erase individual nodes in the tree without the other iterators getting invalidated. Note that I did not increment the iterator in the for loop header itself, since that would skip an element in the case where you erase a node.


    † By now, you should have noticed that this would wreak havoc in the std::map's ordering, which is the reason why the key is const - so you can't influence the ordering in any way after an item has been inserted.

    0 讨论(0)
提交回复
热议问题