2

Possible Duplicate:
Why can templates only be implemented in the header file?

I've struggled with this for a while, and I've taken a look to several questions here, but being new to C++ I haven't been able to understand where I am wrong.

Here is the code, I took it from this page and tried to make it work, but so far I haven't been lucky:

stack.h

#ifndef STACK_H
#define STACK_H
template <class T>
class Stack {
  public:
    Stack(int n);
    ~Stack() { delete[] s; };
  private:
    T* s;
    int _top;
    int _size;
};
#endif // STACK_H

stack.cpp

#include "stack.h"
template <class T>
Stack<T>::Stack(int n) {
  _size = n;
  _top = -1;
  s = new T[_size];
}

main.cpp

#include <iostream>
#include "stack.h"
using namespace std;
int main() {
  Stack<int> s(10); // undefined reference to `Stack<int>::Stack(int)'
  return 0;
}

When I compile (gcc 4.5.2) I get one error: undefined reference to Stack<int>::Stack(int). I've tried several things but without any real knowledge to support what I do. I will be really thankful if somebody can explain me what's going on.

Community
  • 1
  • 1
Janoma
  • 514
  • 4
  • 15
  • Well, it is not a duplicate, though it does solve my problem. I was searching for the error (`undefined reference`), so I didn't find that question before. Thanks! – Janoma Oct 11 '11 at 19:01
  • It seems like there are tons of new people who start learning C++... Is that C++11 effect or something? –  Oct 11 '11 at 19:02
  • @Vlad: Copy-constructor, move-constructor, copy-assignment operator, move-assignment operator, destructor. (4.5 with copy-and-swap: Copy-constructor, move-constructor, assignment-operator, destructor, swap.) – GManNickG Oct 11 '11 at 19:10
  • @GMan I actually ninja-edited the rule of five note into my answer, Vlad was actually pointing out that I had missed it initially. – Mark B Oct 11 '11 at 19:13
  • Have you tried using `std::stack`? – Thomas Matthews Oct 11 '11 at 19:35
  • What is that C++11 effect? I am using C++ for the first time after having used Java, C# and PHP for a while. I am using it because the professor of the courses I'm taking asked us to code the assignments in C or C++, and I chose C++ because I'm used to OOP. – Janoma Oct 11 '11 at 20:24
  • @ThomasMatthews: the idea is to implement all the data structures we need ourselves, but I would definitely consider using established libraries for a real-world project. – Janoma Oct 11 '11 at 20:25

3 Answers3

4

You can only have a template class definition in a cpp file if it's a specialized definition - i.e. you know what T is.

Other than that, and your case belongs here, all definitions of your template class have to go in the header file. The compiler has to know about these each time a new instance is declared or defined because the type, and thus the behavior, changes. Definitions in a cpp file would mean a different translation unit, so the compiler couldn't possibly know about the behavior for every single T you try to apply to your template.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
1

The compiler has to have all of the pertinent information when creating template classes and consequently templates are generally fully implemented in their header files.

There are several ways you could accomplish this, inline functions, defining the template functions in the header file, including your implementation in a separate file (at the end of your header file, with #include), etc.

Here's a similar question with more details.

Community
  • 1
  • 1
Chad
  • 18,706
  • 4
  • 46
  • 63
  • It is possible to have template definitions in cpp file,see [this](http://stackoverflow.com/questions/7418553/private-template-functions/7418808#7418808) – Alok Save Oct 11 '11 at 19:02
  • Don't include .cpp files anywhere. – Luchian Grigore Oct 11 '11 at 19:03
  • It is possible, but they still are required to have all implementation details when instantiated. I've subtly edited my answer. – Chad Oct 11 '11 at 19:04
  • Including `cpp` files my be generally frowned upon, but in the specific case of a `template` implementation (given there is nothing else in that file, as is the case in the OP's question) it serves to bring the implementation into the translation unit making this work as expected. Not sure that is really deserving of a down vote. – Chad Oct 11 '11 at 19:06
  • It's frowned upon because it will define the same symbol twice in different translation units and give an error. – Luchian Grigore Oct 11 '11 at 19:18
  • If it's treated that way by the compiler (which with `gcc` you have to tell it that specifically). Fair enough, since the default for `Visual Studio` is to treat `cpp` files as "compilable", I've edited my answer slightly. – Chad Oct 11 '11 at 19:27
  • @Chad and in return, I removed my downvote. – Luchian Grigore Oct 11 '11 at 20:15
1

There is nothing to compile in "stack.cpp". Templates are only compiled when they are instantiated. Hence the linker cannot find this function which was never compiled.

You can't really separate declarations and implementations in header and source files with templates.

What you can do is copy-n-paste "stack.cpp" to the end of "stack.h". Alternatively include "stack.cpp" at the end of "stack.h", not the other way round, which achieves the same effect. In the latter case it might be wise to change the extension of the "cpp" file (see Including .cpp at end of template header file)

Community
  • 1
  • 1
UncleBens
  • 40,819
  • 6
  • 57
  • 90