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

时间:2015-01-06 20:16:06

标签: c++ templates casting

我遵循了一些C ++教程,令人沮丧的是,源材料声明无法进行此特定函数调用,但根本没有解释原因;

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

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

}

现在我创建一个显式模板函数实例化并传入ab;

int a = 5;
double b = 10.3;

Swap<double>(a, b);

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

  

无法转换&#39; a&#39; (键入&#39; int&#39;)键入&#39; double&amp;&#39;

我唯一的预感是,这是因为规则表明rvalue不能绑定到非const引用,但是,如果T &a只是一个别名,它就是不是右边的本身,是吗?我的隐式演员是创建一个临时的,它不能绑定到T &a?这是发生了什么?

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

我假设我甚至在这里正确的轨道上。

修改

第二个例子;

int a = 5;
double &d = a; // invalid initialization of reference of type 'double&' from expression of type 'int'

然而;

int a = 5;
const double &d = a; //valid

3 个答案:

答案 0 :(得分:5)

直观地说,交换ab应该有效,因为编译器可以在intdouble之间进行转换。但是,在实践中,请考虑编译器必须执行的操作才能执行您所要求的操作。

您从模板开始:

template<typename T>
void Swap(T &a, T &b){
    T temp = a;
    a = b;
    b = temp;
}

要为double实例化它,编译器会创建一个类似这样的函数:

void Swap(double& a, double& b) {
    double temp = a;
    a = b;
    b = temp;
}

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

void Swap(double* a, double *b);

换句话说,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;
}

Demo.

答案 1 :(得分:3)

你要做的是有效:

int a = 5;
double& dr = a;

管理标准中参考初始化的规则在§8.5.3中。首先,一些定义:

  

(4)给定类型“ cv1 T1”和“ cv2 T2,”“ cv1 { {1}}“与参考相关的与” cv2 T1“如果T2T1的类型相同,或者T2T1的基类。 “ cv1 T2参考兼容与“ cv2 T1”如果T2为< em>与参考相关的与T1 cv1 具有相同的cv资格,或者比 cv2 更高的cv资格。

然后,我们有:

  

(5)类型“ cv1 T2”的引用由类型为“ cv2 T1”的表达式初始化,如下所示:

     
      
  • 如果引用是左值引用和初始化表达式   
        
    • 是左值(但不是位字段),“ cv1 T2”与“ cv2 {{1}”引用兼容},”
    •   
    • ..
    •   
  •   
     

然后引用绑定到第一种情况下的初始化表达式lvalue和第二种情况下转换的左值结果

     

- 否则,引用应该是对非易失性const类型的左值引用(即 cv1 应为T1),或者引用应为右值引用。< / p>

“then”案例不适用,因为T2const不是参考兼容的。所以我们转到另一个案例,它说明结果应该是 rvalue 引用。也就是说,引用应为:

int

但这不是你的代码所做的 - 因此错误。实际上,您想要做的事情在标准中明确提到作为同一项目中的反例:

double

答案 2 :(得分:0)

编译器正在寻找Swap(int&, double&),因为您提供了int作为第一个参数,而double作为第二个参数,它无法找到一个参数。

您可以执行以下操作:

int a = 5;
double b = 10.3;
double c = a * 1.0;
Swap<double>(a, c);

基本上,您声明了一个想要引用两个double的函数。当编译器将int转换为double时,它会创建一个临时的。你的功能并不想要一个临时的,因为它可能会修改这个值(参考意味着什么)。

此外,交换带浮点的整数是否有意义?