Specialization / Overload Rules Example

I understand that you cannot partially specialize a function template, I also understand the typical function overload.

In cases where I need help, you can make out the difference between the four foo () functions. I expect some of them to differ from the syntax in the same way?

Can someone more knowledgeable explain for each function what exactly happens in relation to this specialized specialization or template overloading, and how the C ++ compiler determines what to call?

//(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*) 
+5
source share
4 answers

Skip the first call to foo(x) .

int cannot be written as a pointer, unable to output the parameter, the following

 void foo(int* l); 

Cannot convert int to int* implicitly, then

 template<typename T> void foo(T t); 

This seems like a good match, for example, remember 2). Further

 template<> void foo<int*>(int* l); 

Cannot convert int to int* implicitly, then

 template<typename T> void foo(T* l) 

So the only possible match is 2), and therefore template<T> foo(T) is the way out.


The second call, foo(&x) .

 void foo(int* l); 

A function without a pattern that perfectly matches type x . Remember this one.

 template<typename T> void foo(T t); 

Good coincidence! But the previous is even better, the next

 template<> void foo<int*>(int* l); 

Oh, the specialization of the previous template that exactly matches the type is better, but 1) it still matches better. Further

 template<typename T> void foo(T* l) 

Better than specialization, a template without, but not a non-template, beats.

So, at the end, a function without a template is called. Non-templates are always better than templates.

+1
source

Explanations in the 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; } 

Read more about overload resolution and explicit (full) type specialization .

+5
source

The resolution foo(x) easy to determine, since there are no additional functions except template<typename T> void foo(T t) .

So, our problem boils down to: Why void foo(int* l) for foo(&x) call?

  • To call the template method template<> void foo<int*>(int* l) , you need to call foo<int*>(&x)
  • template<typename T> void foo(T* l) , calling foo<int>(&x)
  • template<typename T> void foo(T t) , calling foo<int*>(&x)

As you can see, calling foo(&x) does not match any of the above three calling styles with explicit patterns.

Please note that in the absence of the specialized function void foo(int* l) call to the function foo<int*>(&x) will be resolved using the specialized function template<> void foo<int*>(int* l) , beating the non-specialized template function template<typename T> void foo(T t)

0
source

when trying to determine which function is called upon overload, the rule is: always find a function that requires the least optimization.

when foo () is called using int, the only function that can be used is the first, since you cannot convert int to int *.

when using it with int *:
function 4 can be used without any optimization.
function 3 should change T-> int to start.
function 1, you need to change T to a pointer type and determine that T points to int.
function 2 is a specialization of function 1

therefore, function 4 can be used immediately, function 2 needs to update the template type, and functions 1,2 must update the template type and object type.
therefore, they are called in this order: 4, then 3, then 2, then 1

0
source

Source: https://habr.com/ru/post/1262641/


All Articles