This question is more theoretical and the scope is different from :
Template Specialization VS Function Overloading - Explaining that the compiler does overload resolution before it even looks at specializations
Template specialization vs. Function overloading - Describing the difference between the two mechanisms
Let's get into theoretical questions:
template <typename T>
T add(T a, T b)
{
return a + b;
}
template <>
int add<int>(int a, int b)
{
return a + b; //Specialization
}
int add(int a, int b)
{
return a + b; //Overloading
}
add(3,4); // in Main
1. When to use function full specialization and when to use function overloading?
Why to use template specialization since the templates are parsed twice (at template definition and at instantiation)?
On the other hand, in the case of function overloading, the answer seems pretty obvious: use it when you have a specific, particular case that needs a different logic rather than the template generic one.
2. Is the lookup process (for gcc or clang) going to choose every time the overloading candidate instead of the specialization if the form is the same? By form I mean: function name, number of arguments, argument types.
In the case of full function specialization, when the template functions are candidates, the compiler selects the template instances. Some are chosen, based on the accepted conversions (in order: strict exact match, qualification adjustment, inheritance derived to base conversion for virtual).
In the case of function overloading, among the candidate functions, select the viable ones for the call. Among the viable functions, select the best match for the call. Basically, the compiler checks the conversion strength (in order: strict exact match, qualification adjustment, int/float promotions, conversions, user conversions such as cast).
Normally, in case of ambiguity for the best viable between a template (specialization) and a non-template (overloading), the compiler selects the non-template. But why? How does the lookup mechanism work?
One factor might be the fact that the supported conversions are not the same. Example:
template <typename T>
bool isEqual(const T& a, const T& b); //generic form
template <>
bool isEqual(const string& a, const string& b); //specialization
bool isEqual(const string& a, const string& b); //overloading
bool c = isEqual ("cheers", "noroc"); //in Main, the arguments are const char *
In this case, the specialization does not match since it would require a user-defined conversion const char * -> string which is forbidden in argument deduction context. On the other hand, the overloading match since the user-defined conversion is valid here.
but what if in Main, we give strings as arguments?
string s1, s2;
bool c = isEqual (s1, s2);
Why does the compiler choose the overloading function in this case?