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.这总是与所有其他"普通"类型(如类,基元类型等)一起发生.为什么在处理函数引用时它会有所不同?
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.