简体   繁体   中英

Inconsistent overload resolution with rvalue references

My understanding of overload resolution is that 'T&&' is generally a better match than 'const T&'. However, I'm seeing some inconsistent behavior among compilers with this trivial example:

#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 will print [rvalue] . However, the VS2013 32bit/64bit compilers will print [lvalue] . If I change '5.5f' to '5.5', then both compilers will print [lvalue] .

I can understand why the VS compiler chooses the 'const double&' version since I don't have a std::forward call to preserve the '&&' of the parameter. However, I still don't understand what makes clang think that the '&&' overload is the better choice.

Why does adding an implicit float to double conversion affect the behavior in clang? Who is right?

When you call with 5.5f , T is float, and the Func call effectively becomes Func(double(a)) . The argument is a temporary, and so rvalue overload should be chosen.

When you call with 5.5 , T is double, and no temporary is created in a call to Func(a) . A named variable cannot bind to an rvalue reference, so lvalue overload is the only choice.

MSVC has a long-standing misfeature that allows temporaries to bind to non-const lvalue references. This is why it incorrectly chooses lvalue overload even in the first case. Try compiling with /Za (disable language extensions) - I believe it would match clang's behavior then.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM