Passing a function reference as a universal reference

I am trying to understand what exactly happens when a function-link is passed to a function as a universal link (which type is inferred). Suppose we have a function foo that takes a parameter as a universal reference:

template<typename T> void foo(T&& param) { std::cout << __PRETTY_FUNCTION__ << std::endl; } 

And then do the following:

 void(&f)(int) = someFunction; foo(f); 

The result will be:

void foo(T&&) [with T = void (&)int]

This is completely understandable: we pass an lvalue to our function foo, so the type deduced is void (&) int, and the parameter type is "void (& & & &) int", which, by reference to discard rules, becomes invalid (&) int. The parameter will only be an lvalue reference to the function.

But when I do the following:

 void(&f)(int) = someFunction; foo(std::move(f)); 

foo will print:

void foo(T&&) [with T = void (&)int]

which is exactly the same as before! What's going on here? Why is the result the same as passing lvalue? I would expect that since we pass the rvalue to foo, the type inference should be T = void (int), and param should become void (& &) int. This always happens with all other "normal" types (for example, classes, primitive types, etc.). Why is this different when working with function references?

+5
source share
1 answer

A std::move is the distinguished link type static_cast to rvalue. The standard says that casting an rvalue to a function type still gives an lvalue. Per [expr.static.cast] / p1:

The result of the static_cast<T>(v) expression is the result of converting the expression v to type T If T is a lvalue reference type or a value type reference, the result is an lvalue;

Regarding the category of values โ€‹โ€‹of the function call std::move() , which returns a link to the rvalue indicating the result of the conversion, we can also see from [expr.call] / p10 that the function call is lvalue if its return type is a rvalue reference to function type:

A function call is an lvalue if the result type is a lvalue reference type or an rvalue reference to a function type , an xvalue value if the result type is an rvalue reference for an object type and otherwise.

+6
source

All Articles