我发现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
关闭的状态是什么?
答案 0 :(得分:8)
lambda不是std::function
。引用不会直接绑定 。
案例1之所以有效,是因为lambda可转换为std::function
。这意味着通过复制 std::function
实现了临时fn1
。该临时变量可以绑定到右值引用,因此参数与参数匹配。
复制也是fn1
完全不受foo
中发生的任何事情影响的原因。
答案 1 :(得分:8)
案例1如何以及为什么起作用?
调用foo
需要一个std::function<void()>
实例,该实例绑定到右值引用。 std::function<void()>
可以由任何与void()
签名兼容的 callable对象构造。
首先,从std::function<void()>
构造一个临时[]{}
对象。所使用的构造函数是#5 here,它将闭包复制到std::function
实例中:
template< class F > function( F f );
使用
std::move(f)
初始化目标。如果f
是函数的空指针或成员的空指针,则*this
在调用后将为空。
然后,临时function
实例绑定到右值引用。
函数返回后fn1关闭的状态是什么?
与以前相同,因为它已被复制到std::function
实例中。原始的封盖不受影响。
答案 2 :(得分:5)
函数返回后fn1关闭的状态是什么?
fn1
是无状态的,因为它什么也没捕获。
案例1如何以及为什么起作用?
之所以起作用,是因为该参数的类型与所引用的右值的类型不同。由于类型不同,因此将考虑隐式转换。由于lambda对于此std::function
的参数是可调用的,因此可以通过std::function
的模板转换构造函数将其隐式转换为lambda。转换的结果是prvalue,因此可以与rvalue引用绑定。