Рассмотрим такой пример кода:
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
— это уже тема для отдельной статьи.)