将引用函数作为通用引用传递

rub*_*ict 5 c++ c++11 universal-reference

我很难理解将函数引用作为通用引用传递给函数时究竟发生了什么(正在推导出什么类型).假设我们有一个函数foo,它将param作为通用引用:

template<typename T>
void foo(T&& param)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

然后让我们做以下事情:

void(&f)(int) = someFunction;
foo(f);
Run Code Online (Sandbox Code Playgroud)

结果将是:

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

这是完全可以理解的:我们将lvalue传递给我们的函数foo,因此推导的类型是void(&)int,并且param的类型将是"void(&&&)int",它在参考折叠规则下变为无效(& )INT.Param只是函数的左值引用.

但是当我做以下事情时:

void(&f)(int) = someFunction;
foo(std::move(f));
Run Code Online (Sandbox Code Playgroud)

foo将打印:

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

这和以前完全一样!这里发生了什么?为什么结果与传递左值相同?我希望由于我们将rvalue传递给foo,推导出的类型应该是T = void(int),而param应该变为void(&&)int.这总是与所有其他"普通"类型(如类,基元类型等​​)一起发生.为什么在处理函数引用时它会有所不同?

0x4*_*2D2 6

A std::move是一种美化static_cast到右值的参考类型.标准说,转换为函数类型的右值引用仍会产生左值.Per [expr.static.cast]/p1:

表达式static_cast<T>(v)的结果是将表达式转换v为type 的结果T.如果T是左值引用类型或函数类型的右值引用,则结果为左值;

关于std::move()函数调用的值类别,它返回一个指定转换结果的右值引用,我们也可以从[expr.call]/p10看到函数调用是一个左值,如果它的返回类型是函数的右值引用类型:

如果结果类型是左值引用类型或对函数类型的右值引用,则函数调用是左值;如果结果类型是对象类型的右值引用,则为xvalue,否则为prvalue.