2

I'm not an experienced C++ programmer and I'm having problems compiling. I've got a Heap class that uses a template:

template <class T>
class Heap
{
  public:
    Heap(const vector<T>& values);

  private:
    vector<T> d;

  // etc.
};

And then in a separate implementation file:

template <class T>
Heap<T>::Heap(const vector<T>& values)
{
d = values;

for (unsigned int i = d.size()-1; i > 0; i--) Heapify(ParentIndex(i));
}

// ... more implementation code ...

And finally a main.cc file:

int main (int argc, char *argv[])
{
  vector<int> in;
  unsigned int i;

  while (cin >> i) in.push_back(i);
  Heap<int> h = Heap<int>(in);

  return 0;
} 

I get these compile errors:

g++ -Wall -I/opt/local/include -c -o main.o main.cc
g++ -Wall -I/opt/local/include -c -o heap.o heap.cc
g++ -Wall -o heap main.o heap.o
Undefined symbols:
  "Heap<int>::Heap(std::vector<int, std::allocator<int> > const&)", referenced from:
      _main in main.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
make: *** [heap] Error 1

Why does this not compile? I think the linker is saying it can't find the constructor, but I know it made the object file.

aaronstacy
  • 6,189
  • 13
  • 59
  • 72

2 Answers2

8

Templates need to be defined 100% within the header file. If you have your Heap<T> implementation in a .cc / .cpp file that is the problem. Move all of the code to the header file and it should fix your issue.

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • You can also keep them physically separate by #including the implementations into the header – Cogwheel Oct 27 '09 at 15:06
  • @Cogwheel, true but including a .cpp file is usually a bad sign in code. I prefer either 1) everything in a .h or 2) putting code in a .inl file. The different file extension makes it much clearer what the intent is – JaredPar Oct 27 '09 at 15:09
  • @JaredPar, yep. I usually use .inl. – Cogwheel Oct 27 '09 at 15:12
  • Well, this is a good rule of thumb, but I do define some templates in .cpp file in particular cases (when they are only used in those files). I would need someone with better worlds like litb to offer a full explanation though :) – Matthieu M. Oct 27 '09 at 15:16
3

According to the C++ standard, you can use the export keyword thus:

export template<typename foo>...

However, most compilers don't support this. The C++ FAQ has some more info: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.14

See JaredPar's answer for something that's actually reliable.

Cogwheel
  • 22,781
  • 4
  • 49
  • 67
  • "export" was one of those things the Standards Committee stuck in without prior experience, and it shows. It's hard to implement, and doesn't seem to do what anybody really wants anyway. – David Thornley Oct 27 '09 at 16:53