整数参数调用浮点重载和浮点参数调用整数重载

use*_*756 11 c++ overloading reference rvalue-reference lvalue-to-rvalue

今天我大致遇到了以下代码:

\n
#include <iostream>\n\nvoid f(float&& f) { std::cout << f << "f "; }\nvoid f(int&& i) { std::cout << i << "i "; }\n\nint main()\n{\n    int iv = 2; float fv = 1.0f;\n    f(2);  f(1.0f);\n    f(iv); f(fv);\n}\n
Run Code Online (Sandbox Code Playgroud)\n

神箭链接

\n

正如预期的那样,前两个 f 调用 print 2i 1f

\n

现在对于第二行,我预计它要么根本不编译,因为 iv 和 fv 不是临时变量(因此不能绑定到 r 值引用),要么它创建要传递给函数的变量的副本,从而打印2i 1f再次打印。

\n

然而,不知何故它打印2f 1i,这几乎是我最没想到的事情。

\n

如果将代码复制到 cppinsights 中,它会将调用转换为

\n
f(static_cast<float>(iv));\nf(static_cast<int>(fv));\n
Run Code Online (Sandbox Code Playgroud)\n

所以它看起来非常有意地将整数转换为浮点数,然后将浮点数转换为整数,但我不知道为什么这样做,也不知道如何谷歌。为什么会出现这种情况?导致这个结果的规则是什么?

\n

use*_*570 8

程序的行为可以从引用初始化来理解。

来自dcl.init#ref-5.4

[实施例6:

double d2 = 1.0;
double&& rrd2 = d2;                 // error: initializer is lvalue of related type
int i3 = 2;
double&& rrd3 = i3;                 // rrd3 refers to temporary with value 2.0
Run Code Online (Sandbox Code Playgroud)

-结束示例]


情况1

在这里我们讨论为什么void f(int&& i)调用不可行f(iv)

左值iv无法绑定到调用i中的右值引用参数,因此重载不可行。基本上,这是不允许的,因为它是相关类型的左值。void f(int&& i)f(iv)f(int&&)int&& i = iv;iv


案例2

下面我们讨论一下为什么void f(float&& i)调用是可行的f(iv)

对于调用f(iv),重载是可行的,因为这里首先将void f(float&& f)初始化表达式隐式转换为目标 type( ) 的纯右值,然后可以发生临时物化,以便参数可以绑定到该物化临时值(这是一个xvalue)。ivfloatf2.0f


类似地,对于 call f(fv),重载void f(float&& i)也是不可行的,因为fv它是相关类型的左值。对于调用,可以使用f(fv)重载void f(int&& i),因为首先初始化器被隐式转换为纯右值,然后发生临时物化,以便i可以绑定到物化临时1(类型为int)。