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

Lambda closure lvalues can be passed as rvalue reference parameters

我发现 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 关闭状态是什么?

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

情况 1 有效,因为 lambda 可转换为 std::function。这意味着临时 std::function 通过 复制 fn1 实现。所述临时对象能够绑定到右值引用,因此参数与参数匹配。

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

How and why does case 1 work ?

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

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

template< class F >
function( F f );

Initializes the target with std::move(f). If f is a null pointer to function or null pointer to member, *this will be empty after the call.

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


What is the state of fn1 closure after the function returned ?

和以前一样,因为它被复制到一个std::function实例中。原来的闭包不受影响。

What is the state of fn1 closure after the function returned ?

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

How and why does case 1 work ?

之所以有效,是因为参数的类型与右值引用的类型不同。由于具有不同的类型,因此考虑隐式转换。由于 lambda 是 Callable for the arguments of this std::function,因此它可以通过 std::function 的模板转换构造函数隐式转换为它。转换的结果是纯右值,因此可以与右值引用绑定。