Рассмотрим такой пример кода:
void f(int i)
{
auto g = [i](auto j)
{
return i + j;
};
g = [i](auto j)
{
return i - j;
};
g(1);
}
При компиляции возникнет ошибка в строке
g = [i](auto j)
.Почему так происходит?
Дело в том, что лямбды в C++ — это всего-лишь синтаксический сахар над локальными классами/структурами с определённым [возможно шаблонным] оператором "скобки":
class Lambda1
{
int i;
public:
Lambda1(int i) : i(i) {}
template <class Ty> auto operator()(Ty j)
{
return i + j;
}
};
class Lambda2
{
int i;
public:
Lambda2(int i) : i(i) {}
template <class Ty> auto operator()(Ty j)
{
return i - j;
}
};
void f(int i)
{
auto g = Lambda1(i);
g = Lambda2(i);
g(1);
}
Теперь причина ошибки [в строке
g = Lambda2(i);
] становится очевидной: Lambda1 и Lambda2 — это различные классы, которые ничего не знают друг о друге.Данные классы пришлось сделать глобальными, т.к. C++ всё ещё не поддерживает шаблонные методы в локальных классах.
void f(int i)
{
class Lambda1
{
int i;
public:
Lambda1(int i) : i(i) {}
template <class Ty> auto operator()(Ty j)
{
return i + j;
}
};
auto g = Lambda1(i);
class Lambda2
{
int i;
public:
Lambda2(int i) : i(i) {}
template <class Ty> auto operator()(Ty j)
{
return i - j;
}
};
g = Lambda2(i);
g(1);
}
И в заключение.
Чтобы приведённые примеры кода скомпилировались достаточно заменить
auto g
на std::function<int(int)> g
.(Как работает
std::function
— это уже тема для отдельной статьи.)Комментарии (9)
Lazerate
01.10.2022 00:20+9Да строго говоря вообще малоосмысленный пост. Всё, про что рассказали, так это про уникальность типа лямбды. Можно было уместить в одну строчку: "тип лямбды уникален". Дальше же пошёл какой-то странный вброс о какой-то "будущей фиче С++", непонятно откуда и почему. Можно хотя бы пропозал? Не то чтобы такой пропозал имел шанс пройти.
mapron
01.10.2022 04:02+5cppinsights.io
Можно вставлять С++ код и смотреть его «псевдокод» на более низкоуровневом С++ коде. Например, неплохо для понимания тех же лямбд.
sergio_nsk
01.10.2022 20:07При компиляции возникнет ошибка
Какая ошибка? Вы подумали о тех, кто читает ваш пост в мобильном браузере? О тех, кто будет читать ваш пост в будущем, когда ссылка сдохнет?
kmeaw
02.10.2022 11:50+1Интересно, что очень похожая программа компилируется без проблем:
void f() { auto g = +[](int j) { return 1 + j; }; g = [](auto j) { return 1 - j; }; g(1); }
YDR
02.10.2022 15:26я вот знаю про lambda в python. Хотел узнать, как с этим дела в современном C++, ожидал типа тьюториала(название позволяет ожидать). А увидел понты "я вот смотрите чо знаю" (поймете, если хоть что-то уже понимаете). Разочарован. Пришлось читать другие источники.
Sazonov
Тема не раскрыта. Ни про захват, ни про типы, ни про auto в лямбдах.
У меня недавно на собесе попросили написать аналог std::function, признаюсь честно, пришлось подумать, с ходу не сделал аналог из STL :)