【问题标题】:Passing a reference-to-function as a universal reference将函数引用作为通用引用传递
【发布时间】:2015-09-16 11:49:48
【问题描述】:

我很难理解将函数引用作为通用引用传递给函数时到底发生了什么(推导什么类型)。假设我们有一个函数 foo,它接受一个参数作为通用引用:

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

然后让我们执行以下操作:

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

结果将是:

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

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

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

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

foo 将打印:

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

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

【问题讨论】:

  • 不。 param 有一个名字,根据定义它是一个左值。
  • @KerrekSB 抱歉,这是错误的 - stackoverflow.com/questions/7016777/…
  • @rubix_addict:我的错,谢谢!已移除。我追求的是答案的一部分,但我没有做对。

标签: c++ c++11 universal-reference


【解决方案1】:

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

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

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

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

【讨论】:

  • 非常好的答案。从直觉上讲,对函数类型的引用会有所不同。函数没有状态,因此不能被移动,对函数的引用永远不会改变函数。对函数类型的有效引用始终表现为 const &。尽管它仍然让我想知道为什么有必要明确声明这些转换发生。在没有这条规则的情况下,还能编造出哪些奇怪、毫无意义的代码示例?
  • 啊,太好了!当有多种获取函数 xvalue 的方法时,这似乎有点复杂,对于每种方式,它实际上都会产生一个函数 lvalue,但它就是这样。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 2011-12-16
  • 2013-09-20
  • 2016-11-15
相关资源
最近更新 更多