Как известно, лямбда это сахарок над объектов, у которого перегружен оператор ().
Но как получить ссылку на этот объект внутри этого оператора? Бывает полезно, в том числе для рекурсивного вызова.
Пока что все решения рекурсивных лямбд какой-то отстой. И приходится по старинке в стиле ++03 городить локальную структуру с методом.
Здравствуйте, T4r4sB, Вы писали:
TB>Как известно, лямбда это сахарок над объектов, у которого перегружен оператор (). TB>Но как получить ссылку на этот объект внутри этого оператора? Бывает полезно, в том числе для рекурсивного вызова. TB>Пока что все решения рекурсивных лямбд какой-то отстой.
Здравствуйте, T4r4sB, Вы писали:
TB>Как известно, лямбда это сахарок над объектов, у которого перегружен оператор (). TB>Но как получить ссылку на этот объект внутри этого оператора? Бывает полезно, в том числе для рекурсивного вызова.
Может быть что-то такое:
auto sum = [](auto& func, auto begin, auto end)->int {
return (begin != end) ? func(func, begin + 1, end) + *begin : 0;
};
std::vector<int> v{ 1, 2, 3 };
std::cout << sum(sum, v.begin(), v.end());
Правда уродский синтаксис вызова, но там уже всё уродское, на мой взгляд
Здравствуйте, T4r4sB, Вы писали:
TB>Пока что все решения рекурсивных лямбд какой-то отстой.
+100500
IMHO лямбды — не лучшее решение таких задач.
Что-то подсказывает мне, что изначально авторы лямбд ориентировались на задачи не рекурсивного характера.
Вот, например, поиск в коллекции, тот же std::find_if — весьма удобное (и удобочитаемое) применение лямбд:
Здравствуйте, Videoman, Вы писали:
V>Правда уродский синтаксис вызова, но там уже всё уродское, на мой взгляд
И по сути указатель на лямбду передаётся два раза — потому что вызов лямбды это вызов метода класса, а метод класса и так передаёт первым параметром указатель на экземпляр класса. То есть это как object.foo(object, 1, 2, 3) в вызове не-статичного метода. Ну не уродство?
Здравствуйте, T4r4sB, Вы писали:
TB>И по сути указатель на лямбду передаётся два раза — потому что вызов лямбды это вызов метода класса, а метод класса и так передаёт первым параметром указатель на экземпляр класса. То есть это как object.foo(object, 1, 2, 3) в вызове не-статичного метода. Ну не уродство?
нормальное решение в части стирания типа, которое отлично оптимизируется в релизе. Опиши полностью задачу которую ты решаешь, тогда можно будет что-то конкретно посоветовать. Рекомендуемый подход для рекурсии вызова такой:
using it = typename std::vector<int>::iterator;
std::function<int(it, it)> sum = [&sum](it begin, it end) {
return (begin != end) ? sum(begin + 1, end) + *begin : 0;
};
Здравствуйте, AlexGin, Вы писали:
AG>Здравствуйте, T4r4sB, Вы писали:
TB>>Пока что все решения рекурсивных лямбд какой-то отстой.
AG>+100500 AG>IMHO лямбды — не лучшее решение таких задач. AG>Что-то подсказывает мне, что изначально авторы лямбд ориентировались на задачи не рекурсивного характера. AG>Вот, например, поиск в коллекции, тот же std::find_if — весьма удобное (и удобочитаемое) применение лямбд:
В языках без локальных функций, народ очень быстро начинает использовать лямбды в качестве замены. Так было в шарпе, видимо тоже самое в плюсах происходит..
Здравствуйте, Alexey Nikitin, Вы писали:
AN>Здравствуйте, Videoman, Вы писали:
V>>Правда уродский синтаксис вызова, но там уже всё уродское, на мой взгляд
AN>Синтаксис вызова можно подправить, прикопав уродскость поглубже)
AN>
AN>auto sum = [](auto begin, auto end){
AN> auto sum_impl = [](auto begin, auto end, auto func) -> int {
AN> return (begin != end) ? func(begin + 1, end, func) + *begin : 0;
AN> };
AN> return sum_impl(begin, end, sum_impl);
AN> };
AN>
А если надо захватывать переменные? Перезахватывать их глубже тоже? Нормальная тема.