Why is rval ref binding to lval ref function?

668 views Asked by At

In the code below, is_rvalue_reference returns true. I would expect testRef(int &&) to be called and not testRef(int &), but that's not the case (at least with my Visual Studio 2015 compiler).

Any idea of the reason why ?

void testRef( int&& i )
{
    cout << "called testRef(int&&) " << endl;
}

void testRef( int& i )
{
    cout << "called testRef(int&) " << endl;
}

int main()
{
    int && rvalref = 4;
    cout << "is rval? : " << std::is_rvalue_reference<decltype( rvalref )>() << endl;
    testRef( rvalref );
}

Note that this is different from the question in Rvalue Reference is Treated as an Lvalue?

In that post they are talking about the variable inside the function: it's like asking whether in my example the variable i is an rvalue or an lvalue (the answer being that it is an lvalue in both cases, cause it has an address in both cases).

The whole point of having rvalues and std::move, which is a cast to rvalue, is to allow to select the right overload in functions and constructors. For example both the following cases resolve to a call to testRef(int && i):

int main()
{
  int g = 3;
  testRef(std::move(g));
  testRef(4);
}

But with an rvalue reference it seems not to be the case.

1

There are 1 answers

0
M.M On

rvalref is an identifier for an object. An identifier for an object is always an lvalue.

Expressions never have reference type. The expression rvalref has type int and value category "lvalue".

In the declaration int && rvalref, the && describes how rvalref will be initialized (i.e. by adding a new name to an object denoted by another expression, as opposed to creating a new object), and that's all.

In an expression, the behaviour of the name of an object is the same, whether or not the name was the first name given to that object.

The code decltype(identifier) has special behaviour, compared to decltype(general_expression). It does not give the type and value category of an expression consisting of that identifier. The code decltype((identifier)) would do that. Further reading