我对重载分辨率的理解是'T&&'通常比'const T&'更好地匹配。但是,我看到编译器之间存在一些不一致的行为:这个简单的例子:
#include <iostream>
void Func(const double& a)
{
(void)a;
std::cout << "[lvalue]\n";
}
void Func(double&& a)
{
(void)a;
std::cout << "[rvalue]\n";
}
template <typename T>
void TFunc(T&& a)
{
Func(a);
}
int main ()
{
TFunc(5.5f);
return 0;
}
Clang 3.2将打印 [rvalue] 。但是,VS2013 32位/ 64位编译器将打印 [左值] 。如果我将“5.5f”更改为“5.5”,则两个编译器都将打印 [左值] 。
我能理解为什么VS编译器会选择'const double&amp;'版本,因为我没有std :: forward调用以保留'&amp;&amp;'参数。但是,我仍然不明白是什么让clang认为'&amp;&amp;&amp;'超载是更好的选择。
为什么在double转换中添加隐式浮点会影响clang中的行为?谁是对的?
答案 0 :(得分:8)
当您使用5.5f
拨打电话时,T
是浮动的,Func
电话有效地变为Func(double(a))
。该参数是临时的,因此应该选择rvalue重载。
当您使用5.5
致电时,T
为双倍,并且在调用Func(a)
时不会创建临时值。命名变量不能绑定到右值引用,因此左值超载是唯一的选择。
MSVC有一个长期的错误,允许临时绑定到非const左值引用。这就是为什么即使在第一种情况下它也错误地选择左值超载。尝试使用/Za
进行编译(禁用语言扩展) - 我相信它会符合clang的行为。