LPCWSTR
LPCWSTR

Reputation: 33

Forwarding references for non-reference types

 template<typename T>
 void F(T&& x) {}

If we call it with argument of type int& everything is clear - reference collapsing takes place and we still have lvalue-reference. But what happens if we call it with, for example, int argument. My thoughts: we have deduced type T=int, decorate it with rvalue-reference, so F takes int&& argument and calling it with int type will result in error. But in real F takes such argument as lvalue-reference. Where does lvalue-reference come from? What rules did compiler apply to get int& from int?

Upvotes: 0

Views: 260

Answers (2)

Oliv
Oliv

Reputation: 18051

Since C++17, there is the concept of forwarding reference in the C++ standard. Normaly the template parameter is deduced as a non reference. But for the specific case of a forwarding reference if the corresponding argument is a lvalue, the parameter is deduced as a reference. C++ standard (N4700)[temp.over.deduct.call]/3:

[...]A forwarding reference is an rvalue reference to a cv-unqualified template parameter that does not represent a template parameter of a class template (during class template argument deduction ([over.match.class.deduct])). If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction.[...]

For the concern of function call, it has the same meaning as this equivalent paragraph in the C++11(N337) and C++14(N414) [temp.over.deduct.call]/3:

[...]If P is an rvalue reference to a cv-unqualified template parameter and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction[...]

Upvotes: 2

Revolver_Ocelot
Revolver_Ocelot

Reputation: 8785

Forwarding references deduce lvalue reference for lvalues and rvalue reference for rvalues. For example, even for lvalue of type int&& it will still deduce int& (as it would for lvalue of type int), likewise, for rvalues of type int or int&& it will deduce int&&:

template<typename T>
class show;

template<typename T>
void F(T&& x) 
{ show<decltype(x)>();}

int main() {
    int&& x = 5;
    F(x);
}
main.cpp:6:3: error: implicit instantiation of undefined template 'show<int &>'
int main() {
    F(5);
}
main.cpp:6:3: error: implicit instantiation of undefined template 'show<int &&>'
int main() {
    int x = 5;
    F(x);
}
main.cpp:6:3: error: implicit instantiation of undefined template 'show<int &>'
int main() {
    F([]()->int{return 5;}());
}
main.cpp:6:3: error: implicit instantiation of undefined template 'show<int &&>'

Upvotes: 0

Related Questions