Wednesday, October 29, 2008

c++: specialization of template function

There some differences between template classes and template functions.
In c++ it isn't possible to overload classes but it's possible to overload functions.

Since you are able to overload function you should consider what actually you are doing.
Lets glance at the code below

template<typename T>
void func(T t) 
{
}

template<>
void func<int *>(int *t)
{
}

template<typename T>
void func(T *t)
{
}
Here is template function, specialization of template function and overloaded template function(it's still primary template).
What function will be called in case of
int *i = new int(10);
func(i);
Let's see. We have 2 primary template and 1 template specialization. The standard(13.3.2 Function Template Overloading) says that non-template functions have the highest priority(we don't have any here). Then if there no non-template functions(or none of them suitable) primary-template functions are being examined. There is no defined behavior which would be chosen among the available, probably compiler will ask developer to explicitly specify the template function(we have 2 primary template functions). If there are some specialization of template function compiler can make a decision w/o developer which is the most suitable in case when there is no primary template function that fits better.
In the code above primary template function will be called
template<> void func<int *>(int *t)
Is it possible to call specialized template function for the code below?
int *i = new int(10); func(i);
The answer is yes and the thing that should be done is specialization of overloaded template function
template<>
void
func<int>(int *t)
{
}
This is the specialization of the
template<typename T>
void func(T *t)
{
}
The specialization should appear _after_ the primary template in the code, so the complete piece of code is
template<typename T>
void func(T t) 
{
}

template<>
void func<int *>(int *t)
{
}

template<typename T>
void func(T *t)
{
}

template<>
void func<int>(int *t)
{
}
With this code
template<> void func<int>(int *t)
will be called for
int *i = new int(10);func(i);
The key is that the specialization is not overloading, to be more clear specialization _do_not_ overload functions. Specialization of template function is being examined only after the primary template has been chosen.
The better way I see here is to create non-template function
void func(int *t)
{
}
This one will be chosen first if there is no ambiguity in the prototypes.

No comments: