我很难理解将函数引用作为通用引用传递给函数时究竟发生了什么(正在推导出什么类型)。让我们假设我们有一个函数foo,它将param作为通用引用:
template<typename T>
void foo(T&& param)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
然后让我们执行以下操作:
void(&f)(int) = someFunction;
foo(f);
结果将是:
void foo(T&&) [with T = void (&)int]
这是完全可以理解的:我们将lvalue传递给我们的函数foo,因此推导出的类型是void(&amp;)int,而param的类型将是&#34; void(&amp;&amp;&amp;) INT&#34;根据参考折叠规则变为无效(&amp;)int。 Param只是函数的左值引用。
但是当我做以下事情时:
void(&f)(int) = someFunction;
foo(std::move(f));
foo将打印:
void foo(T&&) [with T = void (&)int]
与以前完全一样!这里发生了什么?为什么结果与传递左值相同?我希望由于我们将rvalue传递给foo,推导出的类型应该是T = void(int),而param应该变为void(&amp;&amp;)int。这总是发生在所有其他&#34;正常&#34;类型(如类,基元类型等)为什么在处理函数引用时会有所不同?
答案 0 :(得分:6)
std::move
是一个美化static_cast
到右值的参考类型。标准说,转换为函数类型的右值引用仍会产生左值。 Per [expr.static.cast] / p1:
表达式
static_cast<T>(v)
的结果是将表达式v
转换为类型T
的结果。 如果T
是左值引用类型或函数类型的右值引用,则结果为左值;
关于std::move()
函数调用的值类别,它返回一个指定转换结果的右值引用,我们也可以从[expr.call] / p10看到一个函数调用是一个左值,如果它return类型是函数类型的右值引用:
如果结果类型是左值引用类型或对函数类型的右值引用,则函数调用是左值,如果结果类型是右值引用,则为xvalue对象类型,否则为prvalue。