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
的模板转换构造函数隐式转换为它。转换的结果是纯右值,因此可以与右值引用绑定。
我发现 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)
. Iff
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
的模板转换构造函数隐式转换为它。转换的结果是纯右值,因此可以与右值引用绑定。