Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rvalue ref and perfect forwarding

I've read few papers about && and I'm just curious if having:

void fnc_1(int&& p)
{
//...
}

void fnc(int&& r)
{
fnc_1(r);//am I suppose to/should I? call it like so:fnc_1(std::forward(r)) 
}

or just passing 'r' is enough?

like image 343
smallB Avatar asked Jan 20 '23 02:01

smallB


2 Answers

fnc_1(r) won't compile, because r is an lvalue, just like any other variable, regardless of type. Yes, that's right, named rvalue references are lvalues, not rvalues.

fnc_1(std::forward(r)) also won't compile, because std::forward is specifically designed not to infer its template argument.

To pass an rvalue, either of the following would work:

fnc_1(std::move(r))
fnc_1(std::forward<int&&>(r))  
fnc_1(std::forward<int>(r))  

Using std::move is the idiomatic way to cast an lvalue to an rvalue, so I would recommend using that.

like image 85
fredoverflow Avatar answered Jan 31 '23 10:01

fredoverflow


The std::forward template is usually for dependent types. Please read this question carefully to see whether it applies here. This is a difficult subject to master, so feel free to update your question with relevant details about your exact problem (using rvalue references for integers isn't terribly exciting...).

I believe your question is about the understanding of the basic properties of rvalue references. The rule of thumb to remember is:

  • whatever has a name is a lvalue (const or not).
  • whatever has no name is a rvalue.
  • Types with && bind to rvalues.

If you have a function...

void foo(SomeClass&& x)
{
    // ... then here x has type SomeClass& !
}

then inside the body, x is a name, and therefore a l value. It really has type SomeClass&. You must use std::move to turn a SomeClass& into SomeClass&&:

void bar(SomeClass&& x)
{
    // Since `x` has a name here, it is a Lvalue.
    // Therefore it has type SomeClass&, what the signature doesn't indicate.

    // We thus have to explicitly turn it into a rvalue:
    foo(std::move(x));
}
like image 25
Alexandre C. Avatar answered Jan 31 '23 08:01

Alexandre C.