6

我正在努力理解将函数引用作为通用引用传递给函数时到底发生了什么(推断出什么类型)。假设我们有一个函数 foo 将参数作为通用引用:

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]

这是完全可以理解的:我们将左值传递给我们的函数 foo,因此推导的类型是 void(&)int,而参数的类型将是“void(&& &)int”,在参考折叠规则下变为 void(& )int。Param 将只是对函数的左值引用。

但是当我执行以下操作时:

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

foo 将打印:

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

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

4

1 回答 1

7

Astd::move是一种美化static_cast的右值引用类型。该标准说,转换为对函数类型的右值引用仍然会产生左值。根据 [expr.static.cast]/p1:

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

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

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

于 2015-06-29T21:25:17.960 回答