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

Sum*_*udu 16 c++ lambda closures rvalue-reference c++14

我发现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;
}
Run Code Online (Sandbox Code Playgroud)

情况2是标准行为(我只是std::function为了演示目的而使用a ,但是任何其他类型的行为都相同)。

案例1如何以及为什么起作用?fn1函数返回后关闭的状态是什么?

Sto*_*ica 8

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

情况1起作用是因为lambda可转换为std::functions。这意味着可以std::function通过复制 来实现临时文件fn1。该临时变量可以绑定到右值引用,因此参数与参数匹配。

而且复制也是为什么fn1完全不受发生的任何影响的原因foo


Vit*_*meo 6

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

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

首先,std::function<void()>从构造一个临时对象[]{}。使用的构造是#5 在这里,它会将封盖进入std::function实例:

template< class F >
function( F f );
Run Code Online (Sandbox Code Playgroud)

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

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


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

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


eer*_*ika 5

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

fn1 是无状态的,因为它什么也没捕获。

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

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