tags:

views:

221

answers:

2

Typically for my templated classes, I include declarations in a .hpp file and templated implementation code in a .t.hpp file. I explicitly instantiate the class in a .cpp file:

template class MyClass< AnotherClass >;

whose object code gets put in a library.

The problem is that if I try to print the object with operator<<, which is declared in the .hpp file and defined in the .t.hpp file as:

template<class T>
std::ostream& operator<<( std::ostream& os, const MyClass<T>& c)
{
    os  << "Hello, I am being output.";
    return os;
}

I get a linker error saying that the right symbol is undefined.

I understand that this is because this templated function is not explicitly instantiated when the class is. Is there a way to get around this other than to include the .t.hpp file any time I want to use operator<< on the class, or to move the templated function code into the .hpp file? Can I explicitly instantiate the function code?

+1  A: 

You can explicitly instantiate function templates

template std::ostream& operator<<(std::ostream&, const MyClass<int>&);

To instantiate a specialization with T = int. The template argument brackets can be omitted if all template arguments can be deduced (like in this case, from the type MyClass<int>. If it can't, for example because the template parameters do not occur in a function parameter type, you have to explicitly specify it

template<typename T> void f() { }
template void f<int>();
Johannes Schaub - litb
+1. I just added the non-deduced case and see you already updated to include that... Grr! :)
j_random_hacker
Thanks! This is just what I needed. I didn't realize templated functions could be explicitly instantiated.
Seth Johnson
+1  A: 

See litb's solution.

For your specific case, the compiler can deduce all template arguments from parameter and return types, but if it could not you could give them explicitly:

template std::ostream& operator<< <T>(std::ostream&, const MyClass<T>&);

This is still allowed if the template arguments can be deduced.

May I ask: Is there a reason why you prefer to explicitly instantiate everything? You are making quite a lot of work for yourself. You will certainly save compilation time by avoiding including the template source code everywhere, but is it worth it in developer time?

j_random_hacker
I have the exact same question. IMHO in most cases developer time > execution time > compilation time.
Shing Yip
This is for a scientific computing code. A lot of my code is templated on dimension: i.e., the template parameter is an unsigned int which can be 1, 2, or 3 depending on whether I'm running a 1-D problem or whatever.Execution time is of utmost importance, and the bit of extra developer time (since I'll virtually never have to modify the template parameter or add more classes) is worth the extra compilation time: I archive the final templated code into a static library which is linked against the various front-ends, unit tests, etc.
Seth Johnson
@Seth: Execution time for explicitly instantiated code will never be better than implicitly instantiated code, and often worse, because the compiler is unable to perform inlining -- it needs to see the template source code for that. This can make a big difference in tight loops. (But you should use an existing CPU-tuned library for numeric primitives like matrix multiplication anyway, as they are usually much faster still.)
j_random_hacker
@j_random_hacker: I didn't mean to suggest that explicit vs implicit instantiation would change the run time (for code that's not specified to be inlined). I do make sure to inline everything that gets called often, especially in the tight "inner" loops; only the "outermost" objects are explicitly instantiated. And I do use other peoples' tuned libraries when I can.
Seth Johnson