4
votes

I'm reading about universal references/forwarding references and this link says that:

Here param is a universal reference:

template<typename T>
void f(T&& param);   

But here param is not a universal reference, it is an rvalue reference:

template<typename T>
void f(const T&& param);

The definition for universal references is given as:

If a variable or parameter is declared to have type T&& for some deduced type T, that variable or parameter is a universal reference.

And I've read that T is a deduced type because of Template argument deduction.

Why is the second case not a universal reference? Does the presence of const T&& param not follow Template Argument Deduction, for some reason? If so, why?

2

2 Answers

8
votes

Foreword: The official term is forwarding reference.

So why is the second case not a universal reference?

Because it is a reference to const. And references to const are not forwarding references.

why?

The whole point of a forwarding reference is that when an rvalue is given as an argument, the parameter will be deduced as reference to non-const rvalue which allows such argument to be moved from when forwarding (while simultaneously allowing lvalues to not be moved from). You cannot move from a reference to const because the argument of the move constructor will be an rvalue reference to non-const which cannot be bound to a reference to const.

The language-lawyer answer is: Because the standard says so:

[temp.deduct.call] A forwarding reference is an rvalue reference to a cv-unqualified template parameter that does not represent a template parameter of a class template ...

6
votes

Because it would defeat the purpose.

Even if it was a forwarding reference, you'd be getting const rvalue references when passing rvalues in. Move semantics require a non-const reference so that the source object may be modified, because the point is stealing the internal state of about-to-expire objects instead of doing a potentially expensive copy.

You'd be left doing copying all the time regardless of value category. So there's no point "forwarding" in this case.