我发现lvalue
lambda闭包总是可以作为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
闭包的状态是什么?
std::function
。引用不会直接绑定。
情况1之所以有效,是因为lambda可以转换为std::function
s。这意味着临时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,因此可以与右值引用绑定。