views:

461

answers:

3

I am having a hard time getting this to work

file: myclass.hpp

Class MyClass {
public:
  template <class T>    
  MyClass &operator<<(const T &val);
};


file: myclass.cpp

template <class T>
MyClass &MyClass::operator<<(const T &val) {
   ...  
}

I can compile this in to a object without a problem, But when other functions try to calling it, this error comes up (for every time << was used).

myclass.cpp: undefined reference to `MyClass& MyClass::operator<< <int>(int const&)'

What am I doing wrong?

+4  A: 

Put the definition of the operator in the .hpp instead of the .cpp. The compiler needs to be able to see the complete definition of the template when it gets instantiated for some new type, so that it can generate the code for this specialization.

There are also some questions and answers about this kind of template related linker errors and different possible solutions in the C++ FAQ Lite.

sth
+8  A: 

If you want to define instances of your template in separate compilation units (which is typically the case) then you can't define template methods in a separate cpp. Every template method must be visible to the compiler when compiling compilation units that use that template class. Therefore when using the template across cpps, the template must be defined in a header. Template's are really ways of generating classes not classes in-and-of-themselves. Therefore when the compiler sees

YourClass<int>

it needs to see the entire YourClass template at compile time to generate a type called

YourClass<int>

and all its methods, which have completely separate methods from say

YourClass<float>

Which means it must see all the C++ source code. If these two uses of the template are instantiated in separate cpp's then the only way only way the compiler can generate both is to fully define the template in one header.

See my answer here for more info.

Thanks for the useful comments that greatly improved this answer

Doug T.
+1, mainly correct, but you can in fact have your template definition in a .cpp file as long as you manually instantiate for all types that will be used in the application. That is, after the definition add: 'template class YourClass<int>; template class YourClass<double>; ...'
David Rodríguez - dribeas
This is the technique used for the GNU gold linker: http://stackoverflow.com/questions/280162/is-there-a-way-to-do-a-c-style-compile-time-assertion-to-determine-machines-en/280164#280164 and http://www.airs.com/ian/gold-slides.pdf . This wrong assertion of yours stopped me from up-voting your two answers :(
Johannes Schaub - litb
Thanks I hadn't fully realized that. Updated my answer.
Doug T.
+2  A: 

Templates need to be defined in the header file rather than the cpp file. The actual implementations are created in each compilation unit on demand as they're used. They're kind of like macros in that respect.

Nik