-3

There are four maps in my program:

std::map< int, SigGen* > id_to_siggen_map;
std::map< int, std::vector< double > > id_to_ticks_map;
std::map< int, std::vector< double > > id_to_samples_map;
std::map< int, QListWidgetItem* > id_to_item_map;

and I want to write a template function that, given an id, can delete from any of the above maps an entry corresponding to that id, i.e.

int id = 4; //could be any other id number
delete_from_map(id, id_to_siggen_map); //deletes entry corresponding to id 4 from id_to_siggen_map
delete_from_map(id, id_to_ticks_map); //deletes corresponding entry from id_to_siggen_map
delete_from_map(id, id_to_samples_map);
delete_from_map(id, id_to_item_map); 

What I have so far:

template <typename T>
void delete_from_map(int id, std::map< int, T > mymap){
  for (auto it = mymap.begin(); it != mymap.end(); it++){
     if(it->first == id){
        mymap.erase(it);
        break;
     }
  }
}

However, attempts to compile give me undefined reference error for each of the four maps. The error looks like the following:

error: undefined reference to `void DVis::delete_from_map<QListWidgetItem*>(int, std::map<int, QListWidgetItem*, std::less<int>, std::allocator<std::pair<int const, QListWidgetItem*> > >)'

What am I doing wrong here?

megamonium
  • 463
  • 3
  • 7
  • 4
    Your attempt looks like it is in the right direction, but please show a [mcve] so we can try to compile it ourselves. Undefined reference errors often mean you have put some part of your code in the wrong place, or messed up your compile command. – BoBTFish Oct 24 '18 at 05:50
  • 5
    Why you don't want to write id_to_siggen_map.erase(id); ? – Öö Tiib Oct 24 '18 at 05:52
  • 3
    Right, doing linear search on a map is a bit awkward. – lubgr Oct 24 '18 at 05:54
  • Yes, the need for a [mcve] is paramount. This is not reproducible with just the code you've shown (http://coliru.stacked-crooked.com/a/ad229c2c59416d68). Did you by any chance simplify too much? Are those maps static members of a class? – StoryTeller - Unslander Monica Oct 24 '18 at 05:55
  • Interesting, I made up a quick example using the code given (replacing object types with primitives) and cannot reproduce the error, it compiles fine for me. – AdaRaider Oct 24 '18 at 05:56
  • 4
    `error: undefined reference` is a linking and not a compiling error. And this indicates that you have tried to _split_ your template function into declaration and definition and that you placed your definition into a cpp file. But this won't work, the file that wants to use the template function needs to know the complete definition of the template function. – t.niese Oct 24 '18 at 05:58

2 Answers2

0

First of all there is no need to use for loop as in map you can directly delete elements by value and secondly it is not a good idea to delete while you are iterating in map as it can cause iterator invalidation (check: http://advancecpptopics.blogspot.com/). As pointed by OP and verified by other people code in question is correct but it could be better if we use variadic template as in future you might have scenario where you have written your own allocator etc. So will suggest you to try below version:

template<typename... Args>
void delete_from_map(int id,std::map<int,Args...>& m)
{
    m.erase(id);
}
PapaDiHatti
  • 1,841
  • 19
  • 26
  • A really great answer doesn't just show **what** to do, but **why** it works - what is the problem in the original and how does this fix it? Also, I suspect that the original problem isn't actually about the template parameters, though there is not enough information in the question to be certain. – BoBTFish Oct 24 '18 at 06:03
  • With a few explanations, this answer would be good – Rerito Oct 24 '18 at 06:06
0

As pointed out by @t.niese, the problem was a linking error caused by separating function definition and declaration. Once I moved the definition into the header, the program compiles and runs.

megamonium
  • 463
  • 3
  • 7