Лямбда-выражения: n3290 draft - PullRequest
4 голосов
/ 13 июля 2011

Точка из ISO проекта n3290: Лямбда-выражения: раздел 5.1.2, пункт 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."

Может ли кто-нибудь объяснить этот момент на примере, пожалуйста?

Ответы [ 2 ]

4 голосов
/ 13 июля 2011

Краткий ответ

Это просто означает, что лямбды, которые ничего не захватывают, могут быть преобразованы в указатель функции с такой же сигнатурой:

auto func = [](int x) { return x * 2; };
int (*func_ptr)(int) = func; // legal.

int y = func_ptr(2); // y is 4.

А захват делает его незаконным:

int n = 2;
auto func = [=](int x) { return x * n; };
int (*func_ptr)(int) = func; // illegal, func captures n

Длинный ответ

Лямбда - это сокращение для создания функтора:

auto func = [](int x) { return x * 2; };

Эквивалентно:

struct func_type
{
    int operator()(int x) const { return x * 2; }
}

func_type func = func_type();

В этом случае func_type - это «тип закрытия» and operator() - это «оператор вызова функции». Когда вы берете адрес лямбды, вы как бы объявляете статический operator() и берете его адрес, как и любая другая функция:

struct func_type
{
    static int f(int x) { return x * 2; }
}

int (*func_ptr)(int) = &func_type::f;

Когда вы захватили переменные, они становятся членами func_type. operator() зависит от этих членов, поэтому его нельзя сделать статическим:

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

Обычная функция не имеет понятия переменных-членов. Следуя этой мысли, лямбды можно рассматривать как обычные функции, только если они не имеют переменных-членов.

2 голосов
/ 13 июля 2011

Это (примерно) говорит о том, что новая лямбда C ++ 0x имеет оператор преобразования в указатель на функцию (с той же сигнатурой).Когда вы вызываете указатель на эту функцию, это все равно, что вызывать лямбду (с теми же переданными параметрами).

... лямбда-выражение без лямбда-захвата ...

«без лямбда-захвата» означает, что вы не захватили какие-либо переменные из содержащей области, поэтому он самодостаточен.

Из этого сообщения я думаю, что вы можетене выполняйте преобразование, если вы захватили переменные (например, из локальной области видимости):

// 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...