måndag 20 april 2009

Template specialization sucks

A wise man (Herb Sutter) once said that you should avoid function template specialization. After what I experienced today, I can only agree.

As we know, the compiler has to do a lot of background work when you declare templates. Unfortunately, all compilers handles templates a little bit differently. Watch this code taken from stackoverflow which was supplies as an answer to me regarding a template problem:

template <typename X> struct Test {}; 
struct X
{
template <typename T>
static void f( Test<T> );
};

// template definition:
template <typename T>
void X::f( Test<T> ) {
std
::cout << "generic" << std::endl;
}
template <>
void X::f<void>( Test<void> ) {
std
::cout << "specific" << std::endl;
}

int main()
{
Test<int> ti;
Test<void> tv;
X
::f( ti ); // prints 'generic'
X
::f( tv ); // prints 'specific'
}
We have here a simple template specialization for the void type. This will compile and run fine under any compiler.

However, often we use multiple static libs. If we instead put the template specification in another lib and linked it to our main application where main() resides, it would still work fine. On some compilers.

It turns out that MSVC can handle this without any problems, while gcc will generate a "multiple definitions" error for f(). Obviously, this has something to do with how the function tables are constructed during linking, but I have not explored it more deeply than that.

As it happens, there's a fix for this problem. Declaring the speccialization as inline will remove the compiler error. With inline , a copy of the function body is inserted everywhere the function is called. No normal calls (including a jump, stack things etc) are done.

However, the point here is that templates in general and template specialization in particular, are advanced concepts that should only be used with uttermost care in your code. There is no way to underestimate the benefits of having code that compiles on all standard compilers. Therefore, follow Sutter's advice and use template specialization only when you really have to.

Inga kommentarer:

Skicka en kommentar