Страницы

Поиск по вопросам

воскресенье, 8 декабря 2019 г.

Как происходит передача аргумента лямбда-выражению?

#cpp #lambda #лямбда_выражение


Изучая лямбда-выражения, столкнулся со стойким непониманием и безрезультативными
попытками самостоятельно разобраться с передачей аргументов лямбда выражениям.

Я знаю, что лямбда может принимать аргумент, если после объявления или где-либо после
написать скобки: (arg);.

Также лямбда может захватывать значения перемемнных [=], [x] и т.д.

Однако, как лямбда получает аргумент, имея подобную конструкцию:

[](int n){/*do something*/},

если нигде после её объявления явно не вызываются "скобки со значением", нет доступных
из лямбды внешних ссылок, и она ничего не захватывает?

Подскажие,  как передаются аргументы лямбда-выражениям в подобных случаях?

using namespace std;

int main()
{   
    list numbers;
    numbers.push_back(13);
    numbers.push_back(42);
    numbers.push_back(99);

    const list::const_iterator result = 
        find_if(numbers.begin(), numbers.end(),[](int n) { return (n % 2) == 0; });

    if (result != numbers.end()) {
        cout << "The first even number in the list is " << *result << "." << endl;
    } else {
        cout << "The list contains no even numbers." << endl;
    }
}


Как я понмаю, лямбда-выражение имеет параметр (int n), однако не вижу где лямбда
принимает этот аргумент. И не понимаю как он мог бы передаваться неявно.

...
using namespace std;

int main()
{
    vector srcVec;
    for (int val = 0; val < 10; val++)
    {
        srcVec.push_back(val);
    }

    int result =
        count_if(srcVec.begin(), srcVec.end(), [] (int _n)
        {
            return (_n % 2) == 0;
        });

    cout << result << endl;

    return EXIT_SUCCESS;
}


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

Может быть я не понимаю какого-то банального принципа, который совершенно тривиален,
но был мной упущен? Спасибо.
    


Ответы

Ответ 1



Функция find_if, count_if 3-м аргументом принимают унарный предикат(UnaryPredicat) - функция, которая на вход принимает один аргумент и возвращает тип bool. Требования к предикатной функции. Внутренняя реализация этих функций из стандартной библиотеки вызывает этот унарный предикат, передавая ей в качестве аргумента текущее "тестируемое значение" из коллекции. Унарный предикатом может быть как лямбда-функция, так и любой реализованный самостоятельно функтор.

Ответ 2



Однако, как лямбда получает аргумент, имея подобную конструкцию: [](int n){/*do something*/}, если нигде после её объявления явно не вызываются "скобки со значением"? find_if(numbers.begin(), numbers.end(),[](int n) { return (n % 2) == 0; }); На самом деле здесь все просто. Лямбду вызывает find_if, то есть эти "скобки со значением" находятся где-то внутри find_if. Вот пример реализации find_if с cppreference: template InputIt find_if(InputIt first, InputIt last, UnaryPredicate p) { for (; first != last; ++first) { if (p(*first)) // <--- Вот они скобки (вызов лямбды) { return first; } } return last; }

Комментариев нет:

Отправить комментарий