I understand you can't partially specialise a function template, I also understand typical function overloading.
Where I need help is in grokking the difference between the below 4 foo() functions. I expect a few of them are different syntax for exactly the same thing?
Could somebody more knowledgeable explain for each function what exactly is happening with regards to is it a template specialisation or overload, and how does the c++ compiler determine what to invoke?
//(1)
template<typename T>
void foo(T t)
{
cout << "template<T> foo(T) " << endl;
}
//(2)
template<>
void foo<int*>(int* l)
{
cout << "template<> foo<int*>(int*) " << endl;
}
//(3)
template<typename T>
void foo(T* l)
{
cout << "template<T> foo(T*) " << endl;
}
//(4)
void foo(int* l)
{
cout << "normal overload foo(int*) " << endl;
}
int main()
{
int x = 0;
foo(x);
foo(&x);
return 0;
}
Program Output:
template<T> foo(T)
normal overload foo(int*)
Explanations in comments:
// the 1st primary function template, overloaded function template
template<typename T>
void foo(T t)
// full template specialization of the 1st function template with T = int*
template<>
void foo<int*>(int* l)
// the 2nd primary function template, overloaded function template
template<typename T>
void foo(T* l)
// non-template function, overloaded function
void foo(int* l)
int main()
{
int x = 0;
foo(x); // only match the 1st function template; the others take pointer as parameter
foo(&x); // call the non-template function, which is prior to templates in overload resolution
return 0;
}
See more details about overload resolution and explicit (full) template specialization.
Let's go through the first call, foo(x)
.
int
can't be written as a pointer, unable to deduce parameter, next
void foo(int* l);
Can't convert int
to int*
implicitly, next
template<typename T>
void foo(T t);
That seems like a good match, like remember it as 2). Next
template<>
void foo<int*>(int* l);
Can't convert int
to int*
implicitly, next
template<typename T>
void foo(T* l)
So, the only possible match is 2), and so template<T> foo(T)
is the output.
Second call, foo(&x)
.
void foo(int* l);
A non-template function which matches perfectly the type of x
. Let's remember this one.
template<typename T>
void foo(T t);
Good match! But the previous one is still better, next
template<>
void foo<int*>(int* l);
Oh, a specialization of the previous template which exactly matches the type, that's better, but 1) is still the better match. Next
template<typename T>
void foo(T* l)
Better than a specialization, a template without, but doesn't beat the non-template one.
And so, in the end, the non-template function is called. Non-templates are always better than templates.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With