Basti
Basti

Reputation: 2438

Forwarding references: reference parameter origin

The whole premise about forwarding references (aka universal references) is, that this function:

template<typename T>
void f(T&&) { }

can result in the template parameter either being int& or int, depending if you call it with int a{}; f(a) or f(5) as example. But this is already a step too far I think. Because when I have a function like

template<typename T>
auto g(T) -> void {}

Then it always resolves the template parameter to int, regardless of the way I call it. And that although a auto h(int&) -> void {} is perfectly legal.

So what what rules are in place that allow the template parameter of f to be a reference, but not that of g?

Upvotes: 3

Views: 357

Answers (2)

batman47steam
batman47steam

Reputation: 33

you can read Effective modern C++ for the answer, first chapter, it says that ,we can think of a function template as looking like this:

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

T and paramType is often differnent, paramType often contains adornments like const or reference qualifiers like const T&

and he talked about this in three cases

  1. paramType is a pointer or reference type
  2. paramType is a universal reference
  3. paramType is neither a pointer nor a reference

your first function is case2, since it needs to deduce the type, && here is a universal reference, and your second function is case3, paramType is neither a pointer nor a reference

During type deduction for a template parameter that is a universal reference, lvalues and rvalues of the same type are deduced to have slightly different types.

  • lvalues of type T are deduced to be of type T&
  • rvalues of type T are deduced to be type T

so f(a) you got f(int& && param) then it comes to the rule of "reference collapsing"

  • rvalue reference to rvalue reference become rvalue reference
  • all other references to references collapse into an lvalue reference

so you got f(int& param)

Upvotes: 0

user17732522
user17732522

Reputation: 76688

There is a specific exception in the template argument deduction rules for the case that a function parameter has the form T&& (cv-unqualified) where T is a template parameter. This special case is as seen in the question known as a forwarding reference.

For forwarding references, if the function argument is an lvalue, then an lvalue reference is deduced for T where usually no reference type would be deduced.

You can see that this really is a special rule just for this case by trying to use e.g. const T&& instead of T&&, for which the special rule does not apply. It will deduce a non-reference type for T in any case, although the function call may then not be possible.

Upvotes: 4

Related Questions