воскресенье, 4 января 2015 г.

Лямбда выражения и алгоритмы STL transform и for_each

Анонимная лямбда функция в С++ в наиболее абстрактном виде выглядит так:
[](){}
или так:
[]() mutable -> T { }
где
[] - список внешних переменных передаваемых внутрь лямбда функции;
() - список аргументов лямбда функции;
T - явно задаваемый тип возвращаемой лямбда функцией значения;
{} - тело лямбда функции.
Рассмотрим простой пример использования алгоритмов for_each и transform:
#include <algorithm>
#include <vector>
#include <iostream>
class functorType1{
public:
        void operator()(double i){
                std::cout << i << std::endl;
        }
};     
class functorType2{
public:
        double operator()(double i){
                return ++i;
        }
};     
int main(int argc, char* argv[]){
        std::vector<double> v;
        functorType1 functorObject1;
        functorType2 functorObject2;
        v.push_back(1);
        v.push_back(2);
        v.push_back(3);
        std::for_each(v.begin(), v.end(), functorObject1);
        std::transform(v.begin(), v.end(), v.begin(), functorObject2);
        std::for_each(v.begin(), v.end(), functorObject1);
        return 0;
}

А теперь то же самое, но с использованием лямбда выражения (они обозначены жирным шрифтом):
#include <algorithm>
#include <vector>
#include <iostream>
int main(int argc, char* argv[]){
        std::vector<double> v;      
        v.push_back(1);
        v.push_back(2);
        v.push_back(3);
        std::for_each(v.begin(), v.end(), [](double i){std::cout << i << std::endl;});
        std::transform(v.begin(), v.end(), v.begin(),  [](double i) ->double {return ++i;});
        std::for_each(v.begin(), v.end(), [](double i){std::cout << i << std::endl;});
        return 0;
}
Это более удобно для использования маленькой функции. Не нужно ее определять где-то. Используется прямо на месте. Получается более удобно читаемый код.
Теперь чуть модифицируем этот код для иллюстрации использования внешних к лямбда функции переменных:
#include <algorithm>
#include <vector>
#include <iostream>
int main(int argc, char* argv[]){
        double var1=10;
        double var2=100;
        std::vector<double> v;
        v.push_back(1);
        v.push_back(2);
        v.push_back(3);
        std::for_each(v.begin(), v.end(), [](double i){std::cout << i << std::endl;});
        std::transform(v.begin(), v.end(), v.begin(),  [var1, var2](double i) ->double {return ++i/var1*var2;});
        std::for_each(v.begin(), v.end(), [](double i){std::cout << i << std::endl;});
        return 0;
}
Все примеры компилировались командой g++ ourSample.cpp -std=c++11на системе Дебиан.

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