无法将'a'(类型'int')转换为'double&'

Mar*_*utt 3 c++ templates casting

我正在关注一些C++教程,令人沮丧的是,源材料声明无法进行这个特定的函数调用,但根本没有解释原因;

template<typename T>
void Swap(T &a, T &b){

    T temp;
    temp = a;
    a = b;
    b = temp;

}
Run Code Online (Sandbox Code Playgroud)

所以,现在我创建一个明确的模板函数实例化和传递ab;

int a = 5;
double b = 10.3;

Swap<double>(a, b);
Run Code Online (Sandbox Code Playgroud)

然后抛出以下编译器错误;

无法将'a'(类型'int')转换为'double&'类型

我唯一的预感是,这是因为规则表明rvalue不能绑定到非const引用,但是,如果T &a只是一个别名,它本身不是rvalue,是吗?我的隐式转换是创建一个临时的,它无法绑定到T &a?那是怎么回事?

temp是一个左值.它可能只有函数范围,但确实存在.那么为什么它不允许隐式转换加倍,然后将引用分配给temp?意图看起来很清楚.我不太明白参考作为参数.如果a被分配给temp,这是一个左值,那么这是不是允许的?

那是假设我在这里正走在正确的轨道上.

编辑:

第二个例子;

int a = 5;
double &d = a; // invalid initialization of reference of type 'double&' from expression of type 'int'
Run Code Online (Sandbox Code Playgroud)

然而;

int a = 5;
const double &d = a; //valid
Run Code Online (Sandbox Code Playgroud)

Jos*_*ley 5

直观地说,交换a并且b应该工作,因为编译器可以在int和之间进行转换double.但是,在实践中,请考虑编译器必须执行的操作才能执行您所要求的操作.

你从一个模板开始:

template<typename T>
void Swap(T &a, T &b){
    T temp = a;
    a = b;
    b = temp;
}
Run Code Online (Sandbox Code Playgroud)

要实例化它double,编译器会创建一个如下函数:

void Swap(double& a, double& b) {
    double temp = a;
    a = b;
    b = temp;
}
Run Code Online (Sandbox Code Playgroud)

这些是参考参数 - 它们指向内存中的实际位置,而不是别名或副本.在引擎盖下,引用的行为类似于指针,因此您可以将此功能视为与此类似,如果它有帮助:

void Swap(double* a, double *b);
Run Code Online (Sandbox Code Playgroud)

换句话说,Swap需要引用(指针)两个内存中的双精度数 - 两个8字节的内存部分(假设double需要8个字节).作为聪明而直观的人,我们知道Swap实现并不需要两个8字节的内存部分,但这就是它的声明方式,因此编译器强制执行它.

要创建一个可以处理混合参数的Swap版本,您必须执行以下操作:

template<typename T1, typename T2>
void Swap(T1& a, T2& b) {
    T1 tmp(a);
    a = b;
    b = tmp;
}
Run Code Online (Sandbox Code Playgroud)

演示.