0

I have this bit of code from a stackoverflow question:

template <typename K, typename V>
bool   exists_in(std::map<K,V> const& haystack, K const& needle) 
{
   return haystack.find(needle) != haystack.end();
}

Being a new user of templates, I still understand what is going on here. Only, I can't seem to apply it.

I have defined

class     Varinfo;                            // meta information about vars
std::map<std::string,VarInfo*>    g_varMap;   // a map between var names and meta-info

In my main c++ code I have this statement:

// various other uses of g_varMap that don't cause errors then

if ( exists_in( g_VarMap, "fred" ) )

that generates this error.

undefined reference to `bool exists_in<std::basic_string<char, 
std::char_traits<char>, std::allocator<char> >, 
VarInfo*>(std::map<std::basic_string<char, std::char_traits<char>, 
std::allocator<char> >, VarInfo*, std::less<std::basic_string<char, 
std::char_traits<char>, std::allocator<char> > >, 
std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, 
std::allocator<char> > const, VarInfo*> > > const&, std::basic_string<char, 
std::char_traits<char>, std::allocator<char> > const&)'

which I completely do not understand.

Can someone tell me why this is complaining? What bitof template knowledge am I missing? I have tried various casting operations on the variable returned by and sent to exists_in() including a std::string( "fred" ). Nothing helped. Some just generated even more meaningless errors.

Community
  • 1
  • 1
Wes Miller
  • 2,191
  • 2
  • 38
  • 64
  • 1
    Where is `exists_in<>` defined? The definition needs to be visible to the caller. – ildjarn Aug 27 '12 at 20:12
  • Your error is a linker error, not a compiler error. – Kerrek SB Aug 27 '12 at 20:15
  • I don't like the template. I would have written: `template bool exists_in(Map const & m, typename Map::key_type const & k) { return m.find(k) != m.end(); }` – Kerrek SB Aug 27 '12 at 20:16
  • 1
    Did you declare the function template in a header and then provide the implementation is a separate file? That will not work, because function templates needs to be *visible* to the compiler at the call site. Move the body of the template to the header. – Praetorian Aug 27 '12 at 20:21
  • @Pretorian +1 for being right. Moving the definition intto the .h did the trick for my version and for kerrek SB's version. If you'll turn this into an answer, I'll give you a "check". Interestingly enough, I have anther template functions split into cpp and h files that do work. Why? – Wes Miller Aug 27 '12 at 20:30
  • Kerrek SB - Please explain. What makes your template superior. Both your template and the original one work great once I followed @pretorian's advice. Yous feels balkier, less obvious to the inexperienced reader. – Wes Miller Aug 27 '12 at 20:32
  • 1
    There are 2 other answers that essentially say the same thing, pick one of those. I don't want to 'litter' with a third one. My guess as to why the other function templates work is because those functions are only called by other functions in the same translation unit so they are visible at the call site. PS: Use @ with no typos to notify a user of a comment @KerrekSB has not been notified of your question above because you didn't use `@` – Praetorian Aug 27 '12 at 20:34
  • 3
    @WesMiller: Mine works for maps with non-default predicates, non-default allocators, and also for unordered maps and sets. – Kerrek SB Aug 27 '12 at 20:36
  • I missed the "at sign" above, so @kerrekSB, Please explain. What makes your template superior. Both your template and the original one work great once I followed Pretorian's advice. Yours feels balkier, less obvious to the inexperienced reader – Wes Miller Aug 27 '12 at 20:59
  • @WesMiller: I did already answer you, just above... – Kerrek SB Aug 27 '12 at 22:04
  • Anyone care to say why someone downvoted me here yet cowardly hid his reason? – Wes Miller Oct 19 '12 at 11:15

2 Answers2

2

Undefined reference means it cannot find the definition in any object file. This is a linker error. You need to define the template method within the header file and not in a separate cpp file.

Your code looks okay, I made a rough approximation, you can see it here: http://codepad.org/UvgeTIoC

anio
  • 8,903
  • 7
  • 35
  • 53
2

If your function were available before the point of call you would have no problem. bear in mind that it is template code, so the full implementation has to be included either directly or indirectly:

#include <map>
#include <iostream>

template <typename K, typename V>
bool   exists_in(std::map<K,V> const& haystack, K const& needle) 
{
   return haystack.find(needle) != haystack.end();
}

int main()
{
  std::map<int, int> m{{1,1},{2,2}};
  std::cout << std::boolalpha;
  std::cout << exists_in(m,2) << "\n";
}

output true.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480