Lambda闭包左值可以作为右值参考参数传递



我发现lvaluelambda闭包总是可以作为rvalue函数参数传递。

请参阅以下简单演示。

#include <iostream>
#include <functional>
using namespace std;
void foo(std::function<void()>&& t)
{
}
int main()
{
// Case 1: passing a `lvalue` closure
auto fn1 = []{};
foo(fn1);                          // works
// Case 2: passing a `lvalue` function object
std::function<void()> fn2 = []{};
foo(fn2);                          // compile error
return 0;
}

情况2是标准行为(我只是使用std::function进行演示,但任何其他类型的行为都是一样的(。

案例1是如何运作的,为什么运作?函数返回后,fn1闭包的状态是什么?

lambda不是std::function。引用不会直接绑定

情况1之所以有效,是因为lambda可以转换为std::functions。这意味着临时std::function通过复制fn1来具体化。所述临时参数能够绑定到右值引用,因此参数与参数匹配。

复制也是fn1完全不受foo中发生的任何事情影响的原因。

案例1如何以及为什么工作?

调用foo需要一个绑定到右值引用std::function<void()>实例。std::function<void()>可以由与void()签名兼容的任何可调用对象构造。

首先,从[]{}构造一个临时的std::function<void()>对象。这里使用的构造函数是#5,它将闭包复制到std::function实例中:

template< class F >
function( F f );

使用std::move(f)初始化目标。如果f是指向函数的空指针或指向成员的空指针,则调用后*this将为空。

然后,将临时function实例绑定到右值引用。


函数返回后fn1闭包的状态是什么?

与以前相同,因为它已复制到std::function实例中。原始闭合不受影响。

函数返回后,fn1闭包的状态是什么?

fn1是无状态的,因为它不捕获任何内容。

案例1是如何工作的,为什么工作?

它之所以有效,是因为参数的类型与被右值引用的类型不同。由于具有不同的类型,因此会考虑隐式转换。由于lambda对于此std::function的参数是可调用的,因此它可以通过std::function的模板转换构造函数隐式转换为它。转换的结果是一个prvalue,因此可以与右值引用绑定。

最新更新