编译如何选择调用哪个模板函数?

时间:2010-04-25 16:36:44

标签: c++

关于以下代码,编译器如何选择调用哪个模板函数? 如果const T&功能被省略,T&总是调用函数。 如果T&功能被省略,const T&总是调用函数。 如果两者都包括在内,结果如下。

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

2 个答案:

答案 0 :(得分:3)

Here是编译器经历过程的简短摘要。它并没有涵盖所有内容,但它可以让你开始。

在这种情况下,决策与非模板化函数相同。给定void f(int&)void f(const int&),第一个将被选择为常规整数,第二个将被选择为const整数。这些参数更好地匹配输入:如果你提供一个你可以修改的变量,它会调用一个可以修改它们的函数,如果你提供一个你无法修改的变量,它会调用一个不能修改它们的函数。

在您的示例代码中,pi2被声明为const int *,是一个指向常量数据的非常量指针。因此,在您的功能中,您可以更改t,但不能更改*t。相比之下,pi3是指向非常数数据的常量指针。因此,您可以更改*t,但不能更改t

如果您稍微更改了代码:

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

在这种情况下,第一个和第三个都将解析为T&版本,因为*pi1*pi3都属于int&类型,因此可以进行修改。 *pi2*pi4都是const int&,因此他们会解决const T&重载问题。

答案 1 :(得分:0)

它是关于变量本身是否是常量: 第一个根本不是恒定的。 第二个指向“不变”的东西,但我们可以改变指向的位置, 第三个和第四个都有一个常量指针,意味着变量本身是const,我们不能改变它指向的任何地方。

typedef const int Cint;
Cint * int1;

显然指向常量int。

typedef int * Pint
const Pint int2

显然是指向非常数int的指针