Consider this code:
template<typename T>
void foo(T&& param){ //In this case && is called universal reference
std:string tmp = std::forward<string>(param);
}
My question is if universal reference type can be deduced why do I still need to call forward ?
Why without forwarding tmp's correct c'tor won't be called even if T's type was deduced.
My second question is about reference collapsing rules:
A& &&
becomes A&
A&& &&
becomes A&&
so according this rules and taking in account universal reference why std::forward signature can't be as follows:
template<class T>
T&& forward(T&& arg){
return static_cast<T&&>(arg);
}
According to the rules from above if T
's type is rvalue reference it will collapse to rvalue reference , if T's type is lvalue reference it will collapse to lvalue reference.
So why std::forward
have two different signatures one for lvalue reference and one for rvalue reference am I missing something ?
My question is if universal reference type can be deduced why do I still need to call forward ?
Because as soon as you give a name to the parameter param
it is an lvalue, even if the function was called with an rvalue, so it wouldn't be forwarded as an rvalue unless you use forward<T>
Why without forwarding tmp's correct c'tor won't be called even if T's type was deduced.
Because param
is an lvalue. To restore the value category of the argument passed to foo
you need to cast it back to string&
or string&&
which means you need to know the type T
was deduced as, and use forward
to do the cast.
So why
std::forward
have two different signatures one for lvalue reference and one for rvalue reference am I missing something ?
It was changed by http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3143.html
There is lots of background info in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3143.html and http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2951.html
The problem with your suggested version is that if you say forward<string>
then the parameter T
is not deduced so doesn't function as a forwarding reference, which means that T&&
can't bind to an lvalue, and it needs to be able to bind to an lvalue in order for forward<string>(param)
to work, because param
is an lvalue there.