Рассмотрим такой пример кода:
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++ всё ещё не поддерживает шаблонные методы в локальных классах.
В будущих версиях 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 — это уже тема для отдельной статьи.)