Programming

Wednesday, January 15, 2014

Workaround for partial function specialization



In C++, functions (including members of classes) can be templated as follows:

template<typename T, typename U> int f(T, U);

You can then specialise this, for example

template<> int f(int, int);
template<> int f(int, double);
This allows you to write a different implementation for different types. Unlike classes, partial specialization of functions is not possible, so if you attempted something

template<typename U> int f(int, U);

then the compiler would complain. This is a limitation of the C++ language, and the reason for this is because partial function specialization is implemented at link-time.  However, the workaround is quite simple. You can do something like
template<typename T> struct overload { };
template<typename T, typename U> int f(T t, U u) 
{
    return f(overload<T>(), overload<U>(), t, u); 
}

Then we can use standard (and less problematic) function overloading to select different functions.  The compiler can happily select the correct overload between
template<typename U> int f(overload<int>, overload<U>, int t, U u);
int f(overload<int>, overload<int>, int t, int u);
int f(overload<int>, overload<double>, int t, double u);
The additional argument, overload<>, will be optimized away by the compiler.