Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rvalue to forwarding references

Tags:

c++

c++11

I'm reading the reference collapsing rules and I have a question: why if I pass a rvalue A to

template<typename T>
void foo(T&&);

T is deduced to be A?

e.g. if I pass std::string() to the function T is deduced to be std::string, why not std::string&&? It would have made more sense to me, what's the rationale behind deducing T to the type itself?

like image 405
Dean Avatar asked Mar 30 '16 11:03

Dean


People also ask

What is a forwarding reference?

I understand that a forwarding reference is "an rvalue reference to a cv-unqualified template parameter", such as in. template <class T> void foo(T&& ); which means the above function can take both l-value and r-value reference.

What are rvalue references good for?

Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.

Can lvalue reference bind rvalue?

An lvalue reference can bind to an lvalue, but not to an rvalue.

What is a forwarding universal reference?

A forwarding reference is an rvalue reference to a cv-unqualified template parameter. 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. Hence, the two mean the same thing, and the current C++ standard term is forwarding reference.


1 Answers

This merely lines up with what we expect in general from template type deduction:

template <class T> void vfoo(T );
template <class T> void lfoo(T& );
template <class T> void cfoo(T const& );
template <class T> void ffoo(T&& );

std::string x;
vfoo(x);            // deduce T = std::string
lfoo(x);            // deduce T = std::string
cfoo(x);            // deduce T = std::string
ffoo(x);            // deduce T = std::string& !
ffoo(std::move(x)); // deduce T = std::string

From the original paper, emphasis mine:

When deducing a function template type using an lvalue argument matching to an rvalue reference, the type is deduced as an lvalue reference type. When deduction is given an rvalue argument, type deduction proceeds just as with other types.

It's the lvalue deduction case that's the exceptional one, which is why it gets an extra sentence in the type deduction rules. The rvalue case is typical - it lines up with the simple mental model of pasting in the deduced types to see what function you end up with. Called T&& with a std::string? Get T = std::string so that the argument reads std::string&&. Check.

like image 94
Barry Avatar answered Oct 11 '22 23:10

Barry