Could someone explain why once is used method c(T*)
and next time d<>(int*)
? methods c
and d
seems identical to me and I cannot figure out why is not the same type of method called.
#include <iostream>
using namespace std;
template<typename T>
void c(T){ cout <<"(T)" << endl; }
template<>
void c<>(int*){ cout <<"(int*)" << endl; }
template<typename T>
void c(T*){ cout <<"(T*)" << endl; }
template<typename T>
void d(T){ cout <<"(T)" << endl; }
template<typename T>
void d(T*){ cout <<"(T*)" << endl; }
template<>
void d<>(int*){ cout <<"(int*)" << endl; }
int main(){
int i;
c(&i);
d(&i);
return 0;
}
Output:
(T*)
(int*)
You just stumbled on an ugly part of C++.
The overload resolution pass, during compilation, is about finding the best overload for the current code. It is executed on a set of function and function templates that was selected by the look-up phase, and aims at identifying one (and only one) overload that is better than others.
For function templates, they are segregated in two groups:
and the overload resolution process has two steps:
In both of your examples, the best "base" function is c(T*)
and d(T*)
, so this is the second step that differ. Why ?
Because, to be a specialization of a function template, said function template has to be declared first.
Thus:
c<>(int*)
is a specialization of c(T)
d<>(int*)
is a specialization of d(T*)
and therefore, when c(T*)
is picked in step 1., then there is no better specialization whilst when d(T*)
is picked, d<>(int*)
is a better specialization.
Because this is tricky, the recommendation by experts... is NOT to use function template specialization. It just mixes weirdly with function template overload.
template <typename T>
void c(T); // 1: function template
template <>
void c<>(int*); // 2: specialization of 1
template<typename T>
void c(T*); // 3: overload of 1
template<typename T>
void d(T); // 4: function template
template<typename T>
void d(T*); // 5: overload of 4
template<>
void d<>(int*); // 6: specialization of 5
// ...
int i;
c(&i); // 3 is more appropriate overload than 1
d(&i); // 5 is more appropriate overload than 4
// and it has the suitable specialization 6
Diagram:
c d
/ \ / \
overloads 1 (3) 4 (5) |
| | | priority
specializations 2 (6) V
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