Здравствуйте, samius, Вы писали:
ГВ>>Напротив. Это как раз полное классическое замыкание с некоторой спецификой, свойственной C++ (явное разделение ссылок и значений, const/mutable, далее по тексту). То, что лямбда не навязывает обязательной модификации жизненного цикла контекста — есть хорошо, и хорошо весьма.
S>Срок жизни такого замыкания ограничен блоком, в котором объявлена лямбда. А значит за пределами этого блока при обращении к лямбде ждет UB.
С передачей переменных (собственно — замыканием) дело обстоит точно так же, как и с передачей фактических параметров в функции, возвратом значений, формированием объектов и т.п. То есть можно, например, создать объект, один из членов которого будет ссылаться на локальную переменную:
class A {
A(int *p) : p_(p){}
int *p_;
};
A foo() {
int a;
return A(&a);
}
Но если так сделать, то ты сам себе недобрый Буратин. Аналогичное ограничение с лямбдами.
S>Т.е. лямбду можно передать аргументом, но вернуть в качестве результата ни лямбду, ни что-то ее использующее нельзя.
Возвращать лямбду как функцию, судя по всему, тоже можно. Вот фрагменты из примеров, которые приведены по той ссылке, что я давал:
function<void (int)> g = [](int n) { cout << n * n * n << " "; };
vector<int> a;
vector<int> b;
// ...
auto prime = [](const int n) -> bool {
if (n < 2) {
return false;
}
for (int i = 2; i <= n / i; ++i) {
if (n % i == 0) {
return false;
}
}
return true;
};
keep_if(a, prime);
keep_if(b, prime);
Вполне себе функции со вполне себе распознаваемой сигнатурой.
S>Как можно говорить о классическом замыкании то что работает как замыкание только в одну сторону?
ИМХО, можно. Просто вопросы согласования жизненных циклов, как обычно, лежат на программисте. Само по себе замыкание от этого неполноценным не становится, но (как это всегда бывает на C++) нужно контролировать, что именно происходит с твоими переменными.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!