A point from n3290 ISO draft: Lambda expressions : section 5.1.2, para 6:
"The closure type for a lambda-expression with no
lambda-capture has a public non-virtual non-explicit const
conversion function to pointer to function having the same
parameter and return types as the closure type’s function
call operator. The value returned by this conversion开发者_运维问答
function shall be the address of a function that, when
invoked, has the same effect as invoking the closure
type’s function call operator."
Can any one explain this point with an example please ?
The short answer
This just means that lambdas not capturing anything can be converted into a function pointer with the same signature:
auto func = [](int x) { return x * 2; };
int (*func_ptr)(int) = func; // legal.
int y = func_ptr(2); // y is 4.
And a capture makes it illegal:
int n = 2;
auto func = [=](int x) { return x * n; };
int (*func_ptr)(int) = func; // illegal, func captures n
The long answer
Lambdas are shorthand to create a functor:
auto func = [](int x) { return x * 2; };
Is equivalent to:
struct func_type
{
int operator()(int x) const { return x * 2; }
}
func_type func = func_type();
In this case func_type
is the "closure type" and operator()
is the "function call operator". When you take the address of a lambda, it is as if you declared the operator()
static and take its address, like any other function:
struct func_type
{
static int f(int x) { return x * 2; }
}
int (*func_ptr)(int) = &func_type::f;
When you have captured variables, they become members of func_type
. operator()
depends on these members, so it can't be made static:
struct func_type
{
int const m_n;
func_type(int n) : m_n(n) {}
int operator()(int x) const { return x * m_n; }
}
int n = 2;
auto func = func_type(n);
An ordinary function has no notion of member variables. Keeping with this thought, lambdas can only be treated as an ordinary function if they also have no member variables.
This is (roughly) saying that the new C++0x lambda has a conversion operator to a function pointer (with the same signature). When you call that function pointer, it is just like invoking the lambda (with the same parameters passed).
...a lambda-expression with no lambda-capture...
"with no lambda-capture" means that you didn't capture any variables from the containing scope, so it is self-contained.
From this blurb, I'm thinking that you can't do the conversion if you captured variables (e.g. from the local scope):
// this is fine...
std::vector<int> some_list;
int total = 0;
std::for_each(some_list.begin(), some_list.end(), [&total](int x) {
total += x;
});
// so is this...
int total = 0;
auto someLambda = [](int x) { return x * 5; };
int (*pointerToLambda)(int) = someLambda;
someFunction(pointerToLambda);
// this won't work, because of capture...
int total = 0;
auto someLambda = [&total](int x) { total += x; return total; };
int (*pointerToLambda)(int) = someLambda;
someFunction(pointerToLambda);
精彩评论