How does the compile choose which template function to call?

c++

Solution

Here is a brief summary of the process the compiler goes through. It doesn't cover everything, but it gets you started.

In this case, the decision is made the same as a non-templated function. Given `void f(int&)` and `void f(const int&)`, the first will be chosen for regular ints, and the second for const ints. The parameters simply match the inputs better this way: if you provide a variable you can modify, it calls a function that can modify them, if you provide a variable you can not modify, it calls a function that can not modify them.

In your sample code, `pi2`, being declared as a `const int *`, is a non-constant pointer to constant data. So within your function, you can change `t`, but not `*t`. By contrast, `pi3` is a constant pointer to non-constant data. So you can change `*t` but not `t`.

If you changed your code slightly:

function(*pi1);
function(*p12);
function(*pi3);
function(*pi4);

In this case, the first and third would both resolve to the `T&` version, because `*pi1` and `*pi3` are both of type `int&` and can therefore be modified. `*pi2` and `*pi4` are both `const int&`, so they resolve to the `const T&` overload.

Problem

Regarding the below code, how does the compiler choose which template function to call? If the const T& function is omitted, the T& function is always called. If the T& function is omitted, the const T& function is always called. If both are included, the results are as below. ``` #include <iostream> #include <typeinfo> template <typename T> void function(const T &t) { std::cout << "function<" << typeid(T).name() << ">(const T&) called with t = " << t << std::endl; } template <typename T> void function(T &t) { std::cout << "function<" << typeid(T).name() << ">(T&) called with t = " << t << std::endl; } int main() { int i1 = 57; const int i2 = -6; int *pi1 = &i1; int *const pi3 = &i1; const int *pi2 = &i2; const int *const pi4 = &i2; function(pi1); ///just a normal pointer -> T& function(pi2); ///cannot change what we point to -> T& function(pi3); ///cannot change where we point -> const T& function(pi4); ///cannot change everything -> const T& return 0; } /* g++ output: function<Pi>(T&) called with t = 0x22cd24 function<PKi>(T&) called with t = 0x22cd20 function<Pi>(const T&) called with t = 0x22cd24 function<PKi>(const T&) called with t = 0x22cd20 */ /* bcc32 output: function<int *>(T&) called with t = 0012FF50 function<const int *>(T&) called with t = 0012FF4C function<int *>(const T&) called with t = 0012FF50 function<const int *>(const T&) called with t = 0012FF4C */ /* cl output: function<int *>(T&) called with t = 0012FF34 function<int const *>(T&) called with t = 0012FF28 function<int *>(const T&) called with t = 0012FF34 function<int const *>(const T&) called with t = 0012FF28 */ ```

Original source