使用右值引用的重载分辨率不一致

lhu*_*ous 5 c++ c++11

我对重载决策的理解是'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;
}
Run Code Online (Sandbox Code Playgroud)

Clang 3.2将打印[rvalue].但是,VS2013 32位/ 64位编译器将打印[左值].如果我将'5.5f'更改为'5.5',则两个编译器都将打印[左值].

我可以理解为什么VS编译器会选择'const double&'版本,因为我没有std :: forward调用来保存参数的'&&'.但是,我仍然不明白是什么让clang认为'&&'超载是更好的选择.

为什么在double转换中添加隐式浮点会影响clang中的行为?谁是对的?

Igo*_*nik 8

当你打电话时5.5f,T浮动,Func呼叫有效Func(double(a)).该参数是临时的,因此应选择rvalue重载.

当你打电话时5.5,T是双倍的,并且在通话中没有创建临时Func(a).命名变量不能绑定到右值引用,因此左值超载是唯一的选择.

MSVC有一个长期存在的错误,它允许临时数据绑定到非常量左值引用.这就是为什么即使在第一种情况下它也错误地选择左值超载.尝试编译/Za(禁用语言扩展) - 我相信它会匹配clang的行为.