开发者

Lambda expressions : n3290 draft

开发者 https://www.devze.com 2023-03-19 16:58 出处:网络
A point from n3290 ISO draft: Lambda expressions : section 5.1.2, para 6: \"The closure type for a lambda-expression with no

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);
0

精彩评论

暂无评论...
验证码 换一张
取 消