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