0

While searching for an answer to another question I developed a a helper class that would work with any kind of container of integers. Specifically, my class would lookup container values based on some criteria. In order to work with different types of containers, my class obviously needs to operate not on containers themselves but on their iterators. I don't need to reference containers anywhere in my class, I use only iterators and only in class constructor.

// Header file.

 class MyLookup {
    public: 
    template<typename ForwardIt>   // Forward iterator though sequence of integers
    MyLookup(ForwardIt begin, ForwardIt end)
    ...
 }

// Implementation file

 template<typename ForwardIt>
 MyLookup::MyLookup(ForwardIt begin, ForwardIt end) {
 ...
 }

// Use file

std::vector<int> foo;
...
MyLookup lookup(foo.begin(), foo.end());

While using CLang the initial compiler pass succeeds but then I get linker errors:

Undefined symbols for architecture x86_64: "MyLookup::MyLookup >(std::__1::__wrap_iter, std::__1::__wrap_iter)", referenced from: ...

Any idea what am I doing wrong?

Community
  • 1
  • 1
LRaiz
  • 667
  • 7
  • 18
  • 5
    Templates can't not be in .cpp files. Put the implementation of the file in the .hpp. – NetVipeC Jul 23 '14 at 19:42
  • You need to put implementation in the header where the class definition is. – 101010 Jul 23 '14 at 19:44
  • 1
    @NetVipeC +1 for stating his problem, but that is inaccurate. Templates are normally not in C++ files because they need the full implementation at build time. But exported template specializations and templates only needed in one compilation unit can be in the C++ file. Its just pretty darn uncommon. – IdeaHat Jul 23 '14 at 19:45
  • 2
    @NetVipeC well, more specifically, the template declaration and definition must reside in the same file. So if you want to use it in more than one place, it all needs to be in the header. – aruisdante Jul 23 '14 at 19:45
  • 2
    @aruisdante "same file" ==> "same *translation unit*", and I concur (explicit instantiation not withstanding, which is *way* outside this OP's problem). – WhozCraig Jul 23 '14 at 19:47
  • @WhozCraig ah true true, fair enough. – aruisdante Jul 23 '14 at 19:48
  • @LRaiz [Read this](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file). It doesn't apply only to classes. – WhozCraig Jul 23 '14 at 19:49

1 Answers1

0

You need to provide the definition for your templates in header files, not their own source files. This is because templates are literally templates for class definitions -- they are not class definitions themselves.

bfair
  • 1,101
  • 7
  • 16
  • 2
    Putting in an answer what three different people have already placed in comments without adding any additional information is poor form to say the least. – aruisdante Jul 23 '14 at 19:47
  • Sorry, but I answered the question and provided some additional conceptual information about why template implementations don't reside in their own source files. So I don't see why I wouldn't put this as an answer. – bfair Jul 23 '14 at 19:54
  • Moving constructor definition to the header file indeed solved the problem. I was probably confused because I do have instances of template definition defined in cpp files. These examples must relate to cases mentioned in comments to original question. In all honesty this is already 2nd time I am tripped by the header/implementation/template issue. Thanks everyone. – LRaiz Jul 23 '14 at 19:58
  • 1
    @aruisdante That should not mean that noone can answer the question anymore. I often wonder why people put answers in the form of comments. – leemes Jul 23 '14 at 20:03