[C++11] Гарри Поттер и Возвращение Лямбды

doublemother

Возникло у меня желание, как и во всяких модных языках, динамически генерить функцию. Классическое решение проблемы, путём использования функционала, не так интересно, я захотел сделать примерно так:
auto generateFun(const QString &search, const QString &replacement)
{
return [=](const QString &word) -> QString
{
QString wordFixed = word;
wordFixed.replace(search, replacement);
return wordFixed;
}
}

Вышеупомянутый код не заработает по той простой причине, что сказать "auto" я не могу — для функции я таки обязан указать возвращаемый тип, который ни указать, ни вывести при помощи decltype я не могу.
GCC возвращаемое значение при компиляции обзывает: 'generateFun(const QString&, const QString&)::<lambda(const QString&)>', но и такую конструкцию, очевидно, нельзя указать в качестве возвращаемого значения.
Отсюда вопрос: как можно таки вернуть лямбду?

lipa

 auto generateFun(const QString &search, const QString &replacement)->std::function<QString(const QString &)> 

а полностью автоматическое auto для возвращаемого типа вроде убрали

rosali

а объясните мне популярно, как такое может в с++ работать? ссылки на search и replacement ведь могут стать невалидными после вызова generateFun, но до вызова того что она вернет.

lipa

При использовании [=] сохраняются значения переменных
Вот если бы вместо этого было [&], то да, был бы выстрел в ногу

doublemother

Ха, так сработало, о std::function я не подумал, спасибо. Полностью полноценные функции правда получить не получается: если воткнуть в возвращаемую функцию static переменную, то при создании новых функций (после первой созданной) она не инициализируется, видимо, считается одной общей на все функции.

erotic

так сработало
Добавив, по всей видимости, виртуальный вызов.

istran

Можно возвращать лямбду из другой лямбды:

#include <iostream>

auto l1 = [] (int i) {
return [=](int j) { return i * j;};
};

int main {
auto mul2 = l1(2);
auto mul10 = l1(10);
std::cout << mul2(5) << " " << mul10(5) << std::endl;
}
Оставить комментарий
Имя или ник:
Комментарий: