简体   繁体   中英

Passing a reference-to-function as a universal reference

I'm struggling to understand what exactly happens when passing a reference-to-function to a function as a universal reference (what type is being deduced). Let's suppose we have a function foo that takes a param as a universal reference:

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

And then let's do the following:

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

The result will be:

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

This is perfectly understandable: we are passing lvalue to our function foo, so the deduced type is void(&)int, and the type of the param will be "void(&& &)int" which under reference collapsing rules becomes void(&)int. Param will be just an lvalue reference to a 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 is happening here? Why the result is the same as when passing lvalue? I would expect that since we are passing rvalue to foo, the deduced type should be T = void(int), and param should become void(&&)int. This always happen with all other "normal" types (like classes, primitive types, etc.) Why is it different when dealing with function references?

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

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

Concerning the value category of the std::move() function call, which returns an rvalue reference designating the result of the conversion, we can also see from [expr.call]/p10 that a function call is an lvalue if its return type is an rvalue reference to function type:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM