Skip to main content
AI Assist is now on Stack Overflow. Start a chat to get instant answers from across the network. Sign up to save and share your chats.
3 of 3
Commonmark migration

In perfect forwarding, std::forward is used to convert the named rvalue reference t1 and t2 to unnamed rvalue reference. What is the purpose of doing that? How would that effect the called function inner if we leave t1 & t2 as lvalue?

template <typename T1, typename T2> void outer(T1&& t1, T2&& t2) { inner(std::forward<T1>(t1), std::forward<T2>(t2)); } 

If you use a named rvalue reference in an expression it is actually an lvalue (because you refer to the object by name). Consider the following example:

void inner(int &, int &); // #1 void inner(int &&, int &&); // #2 

Now, if we call outer like this

outer(17,29); 

we would like 17 and 29 to be forwarded to #2 because 17 and 29 are integer literals and as such rvalues. But since t1 and t2 in the expression inner(t1,t2); are lvalues, you'd be invoking #1 instead of #2. That's why we need to turn the references back into unnamed references with std::forward. So, t1 in outer is always an lvalue expression while forward<T1>(t1) may be an rvalue expression depending on T1. The latter is only an lvalue expression if T1 is an lvalue reference. And T1 is only deduced to be an lvalue reference in case the first argument to outer was an lvalue expression.

sellibitze
  • 28.3k
  • 3
  • 80
  • 98