开发者

How does the compile choose which template function to call?

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
*/


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.


it's about whether the variable itself is constant: the first one is not at all constant. the second one points to something that ìs constant, but we could change where it points to, the third and fourth both have a constant pointer, meaning the variable itself is const, we can't change wherever it points to.

typedef const int Cint;
Cint * int1;

obviously pointer to constant int.

typedef int * Pint
const Pint int2

obviously constant pointer to non-constant int

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜