Рассмотрим такой пример кода:

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

Комментарии (9)


  1. Sazonov
    01.10.2022 00:17
    +4

    Тема не раскрыта. Ни про захват, ни про типы, ни про auto в лямбдах.

    У меня недавно на собесе попросили написать аналог std::function, признаюсь честно, пришлось подумать, с ходу не сделал аналог из STL :)


  1. Lazerate
    01.10.2022 00:20
    +9

    Да строго говоря вообще малоосмысленный пост. Всё, про что рассказали, так это про уникальность типа лямбды. Можно было уместить в одну строчку: "тип лямбды уникален". Дальше же пошёл какой-то странный вброс о какой-то "будущей фиче С++", непонятно откуда и почему. Можно хотя бы пропозал? Не то чтобы такой пропозал имел шанс пройти.


  1. mapron
    01.10.2022 04:02
    +5

    cppinsights.io
    Можно вставлять С++ код и смотреть его «псевдокод» на более низкоуровневом С++ коде. Например, неплохо для понимания тех же лямбд.


  1. Kelbon
    01.10.2022 16:25
    +1

    Ни слова пользы в статье, только мифы и ненужный std function


    1. F0iL
      01.10.2022 17:44
      +1

      Почему std::function "ненужный"?


      1. Kelbon
        02.10.2022 20:24
        -2

        Потому что здесь не нужен


  1. sergio_nsk
    01.10.2022 20:07

    При компиляции возникнет ошибка 

    Какая ошибка? Вы подумали о тех, кто читает ваш пост в мобильном браузере? О тех, кто будет читать ваш пост в будущем, когда ссылка сдохнет?


  1. kmeaw
    02.10.2022 11:50
    +1

    Интересно, что очень похожая программа компилируется без проблем:

    void f()
    {
        auto g = +[](int j)
        {
            return 1 + j;
        };
        g = [](auto j)
        {
            return 1 - j;
        };
        g(1);
    }


  1. YDR
    02.10.2022 15:26

    я вот знаю про lambda в python. Хотел узнать, как с этим дела в современном C++, ожидал типа тьюториала(название позволяет ожидать). А увидел понты "я вот смотрите чо знаю" (поймете, если хоть что-то уже понимаете). Разочарован. Пришлось читать другие источники.