воскресенье, 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на системе Дебиан.

суббота, 3 января 2015 г.

Строковые типы в Windows, часть 2

Если мы работаем со строками STL в Windows и хотим быть независимыми от значения переменной _UNICODE (то есть писать код независимый от того работаем ли мы со строками UNICODE или нет), то тогда можно воспользоваться таким куском кода:
#ifdef _UNICODE
#define tstring wstring
#else
#define tstring string
#endif
Если воспользоваться фактом, что std::string и std::wstring являются typedef шаблона класса std::basic_string, то можно сделать так:
namespace std
{
 typedef basic_string<TCHAR> tstring; 
}

Наиболее общее решение выглядит так:

#include  <tchar.h>
#include  <string>
#include  <fstream>
#include  <sstream>
namespace std
{
typedef basic_string<TCHAR> tstring;
typedef basic_ostream<TCHAR> tostream;
typedef basic_istream<TCHAR> tistream;
typedef basic_iostream<TCHAR> tiostream;
typedef basic_ifstream<TCHAR> tifstream;
typedef basic_ofstream<TCHAR> tofstream;
typedef basic_fstream<TCHAR> tfstream;
typedef basic_stringstream<TCHAR> tstringstream;
}
Взято отсюда.

Графическое представление системы ввода-вывода в STL