tags:

views:

64

answers:

3

when i try to remove an element: i go to secondMap which contains in second field a pointer to the first map, now when i try to erase it it gives me problems:

multimap<SortKey,T> firstMap;
multimap<SearchKey,pair<const SortKey,T>*> secondMap;



   template <class T,class SortKey, class SearchKey> T GarageDataBase<T,SortKey,SearchKey>::Remove(SearchKey toRemove) 
{
 multimap<SearchKey,pair<const SortKey,T>*>::iterator it;
 it=secondMap.find(toRemove);
 multimap<SortKey,T>::const_iterator itr;
 itr=(it->second);//pointer to a pair in the first map
 firstMap.erase(itr);

}

i get:

error C2664: 'std::_Tree_iterator<_Mytree> std::_Tree<_Traits>::erase(std::_Tree_const_iterator<_Mytree>)' : cannot convert parameter 1 from 'std::_Tree_const_iterator<_Mytree>' to 'std::_Tree_const_iterator<_Mytree>'

error C2678: binary '=' : no operator found which takes a left-hand operand of type 'const std::pair<_Ty1,_Ty2>' (or there is no acceptable conversion) 

any idea?

A: 
  1. erase() is not going to work on a const iterator.
  2. you cannot use an iterator from one collection to erase an element in another.
  3. You should check find() does not return end() to avoid badness on result access

    multimap<SearchKey,pair<const SortKey,T>*>::iterator it; it=secondMap.find(toRemove);

     if (it != secondMap.end())
     { 
      multimap<SortKey,T>::iterator itr;
      itr=firstMap.find(it->second->first);//find matching element in the first map
    
    
      if (itr != firstMap.end())
      { 
       firstMap.erase(itr);
      }
     }
    

EDIT: The design you have here is going to result in a string of increasingly difficult questions and then hard-to-fix bugs. I would reconsider storing pointers like this. If the values in firstMap are identical who cares which particular value gets deleted? My guess is that you need to know this so you can manage the pointers properly.

Better approaches could be:

  • use a boost::shared_ptr as your container value so that refcounting is not your problem - the final erase() just does delete for you don't use pointers at all.
  • unless your objects are expensive to copy, don't use pointers, just use object instances as your container value. Then resource management is much less of an issue.
Steve Townsend
I got what you meant in the solution u proposed the thing is that the firstMap is a multimap so it can contain identical val's of first, how can i know for sure that it deletes the one i have by pointer in it->second?
Nadav
See upcoming edit
Steve Townsend
Thank you for your replay, The values in the first map aren't Identical(second field in this map), the keys are(or can be).. when i want to remove from firstMap, the Second of secondMap is a pointer to a pair in first map which i also want to remove, i would use erase in it but erase only gets iterators, how can i transform the pointer i have to a pair in the first map into "iterator" type so i can use remove on it and remove it from the first map?
Nadav
You can do that by using the data found in secondMap to locate the corresponding data in firstMap - see the code I included which does call erase) on firstMap using an iterator.
Steve Townsend
from what i get from ur code, i will find the first key that matches on the firstMap, when i need the specific map-node which contains what my pointers is pointing to. how do i mange not to find other datas with same key on the firstMap? for example if the keys in the firstMap are integers i might find an int which matches it->second->first key however its not the one i was looking for since there might be another identical int (key) that is the key of the pair that i am looking for (which my pointer points at)
Nadav
Your comment that "i will find the first key that matches on the firstMap, when i need the specific map-node which contains what my pointers is pointing to" supports my assertion that your data structures do not match your requirements. I think you will have a hard time making this work cleanly.
Steve Townsend
+1  A: 

A pointer and an iterator are not the same thing. You cannot assign a pair<X,Y>* to a map<X,Y>::const_iterator.

In some cases iterators are simply typedef'ed pointers (this is usually the case with std::vector, for example), but it's not something that your code should rely on, and either way it is generally not true with std::map implementations, because the iterators need additional information stored in them in order to traverse the tree structure that the map is normally implemented as.

Tyler McHenry
i was thinking this was probably the reason but couldn't come up with an alternative on how to delete it? how can i delete an object from a map when i have a pointer to it which isn't an iterator??
Nadav
+1 for sound advice
Steve Townsend
@mizi First of all, if you're storing a pointer to the internal representation of an element in the map, why not just store an iterator? They've got all the same problems with invalidation, but the iterator lets you do other things like delete the element. But really what you should be doing is just storing the key. Store a `pair<const SortKey, T>` (not a pointer!) in `firstMap`, then when you want to delete the corresponding element from `secondMap`, iterate through every element of `secondMap` with the given key, and delete the one that has the value you're looking for.
Tyler McHenry
A: 

Use the correct type as the value of the second map, not a pointer. Using typedef will be easier to see what you are really doing:

typedef std::multimap<SortKey,T> first_mmap;
typedef std::multimap<SearchKey, typename first_mmap::iterator > second_mmap;

first_mmap firstMap;
second_mmap secondMap;

You cannot erase a const iterator, so remove the const:

second_mmap::iterator it = secondMap.find(toRemove);
first_mmap::iterator itr = it->second;

You should treat the case when you don´t find the key in the secondMap:

if (it == secondMap.end()) ...; // handle the error
fnieto
i got what u are saying and removed the const, still i can't assign a pointer into the iterator, so i can't delete it from the first map. this itr=(it->second); doesn't compile.. i'm searching for a way to transform the pointer i have into an iterator pointer so i can use erase on it?
Nadav
there is no pointer in my answer. You need to change it for an iterator
fnieto