1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//Листинг #1 C++ Функциональные адаптеры #include <iostream> #include <functional> //для bind using std::cout; using std::bind; void foo(const int x){ //функция с одним параметром cout << x << '\n'; //выводим значение параметра на экран } int main(){ bind(foo, 100); //так выглядит само сохранение в адаптер функции и значения для параметра bind(foo, 222)(); //вызов подобен вызову функции, на экране увидим 222 auto f1 = bind(foo, 333); //можно сохранить, чтобы вызвать потом f1(); //вызываем, видим 333 } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
//Листинг #2 С++ Функциональные адаптеры #include <iostream> using std::cout; struct bind{ //это наш bind, а не встроенный void operator() (void (*func)(const int), int value){ //перегруженные скобки принимают указатель на функцию x = value; f = func; } void operator() (){ //перегрузка () для использования f(x); } int x; void (*f)(const int); }; void f(int value){ cout << value << '\n'; } int main(){ bind b; b(f, 255); //сохранили для параметра 255 b(); b(); //в любом вызове задействуется сохранённая функторе часть b(f,777); b(); } |
1 2 3 4 5 6 7 8 9 |
#include <iostream> #include <functional> //для multiplies using std::multiplies; using std::cout; int main(){ cout << multiplies<>()(5,7); //35 cout << multiplies<>()(7,7); //49 } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//Листинг #3 С++ Использование алгоритма transform #include <iostream> #include <algorithm> #include <vector> using std::transform; using std::cout; using std::vector; int func(const int x){ //функция-задача для алгоритма return x * 5; //значение будет умножено на 5 } int main(){ vector<int> v = {1,2,3,4,5}; //какой-то вектор со значениями vector<int> out(v.size()); //вектор для сохранения преобразования transform(v.begin(), v.end(), out.begin(), func); //алгоритм преобразования for_each(v.begin(), v.end(), [](const int i){ cout << i << '\n';}); //вывод на экран } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
//Листинг #4 С++ Функциональные адаптеры #include <iostream> #include <algorithm> #include <vector> #include <functional> using std::transform; using std::cout; using std::vector; using std::multiplies; int mult(int x, int y){ return x * y; } int main(){ vector<int> v = {1,2,3,4,5}; //какой-то вектор со значениями vector<int> out(v.size()); //вектор для сохранения преобразования transform(v.begin(), v.end(), out.begin(), mult(???,7)); //а тут возникает вопрос } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
//Листинг #5.1 С++ Функциональные адаптеры Пишем свой функтор и функциональный адаптер для использования функтора в std::transform #include <iostream> #include <functional> #include <vector> #include <algorithm> using std::vector; using std::transform; using std::begin; using std::end; using std::cout; using std::for_each; /*описание нашего собственного функтора умножения*/ struct mult{ //Структура будущего функтора int operator()(int x, int y) { //функтор с двумя входящими параметрами return x * y; } }; /*структура нашего собственного функционального адаптера*/ struct bind_{ mult func; //атрибут, объект-функтор int x; //первый множитель bind_(const mult func, const int x):func(func),x(x){} //конструктор по умолчанию принимает функтор и первый множитель int operator()(const int y) { //хотя принимаем один параметр (второй множитель), return func(x,y); //вызываем функцию с двумя параметрами } }; int main(){ vector<int> v{1,2,3,4,5}; vector<int> out(v.size()); transform(v.begin(), v.end(), out.begin(), bind_(mult(), 4)); for_each(out.begin(), out.end(), [](const int i){ cout << i << '\n';}); //выводим на экран (4,8,12...) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
//Листинг #5.2 С++ Функциональные адаптеры Пишем свой функтор и функциональный адаптер для использования функтора в std::transform #include <iostream> #include <functional> #include <vector> #include <algorithm> using std::vector; using std::transform; using std::begin; using std::end; using std::cout; using std::for_each; using std::multiplies; using std::bind1st; int main(){ vector<int> v{1,2,3,4,5}; vector<int> out(v.size()); transform(v.begin(), v.end(), out.begin(), bind1st(multiplies<int>(), 4)); for_each(out.begin(), out.end(), [](const int i){ cout << i << '\n';}); //выводим на экран (4,8,12...) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
//Листинг #6 С++ Функциональные адаптеры std::bind1st и ваш собственный функтор Возникновение проблемы #include <iostream> #include <functional> #include <vector> #include <algorithm> using std::vector; using std::transform; using std::begin; using std::end; using std::cout; using std::for_each; using std::bind1st; class MyFunctor{ public: int operator() (int x, int y){ //наш собственный функтор return x * y; //умножаем значения } }; int main(){ vector<int> v{1,2,3,4,5}; vector<int> out(v.size()); transform(v.begin(), v.end(), out.begin(), bind1st(MyFunctor(), 4)); for_each(out.begin(), out.end(), [](const int i){ cout << i << '\n';}); //выводим на экран (4,8,12...) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
//Листинг #7.1 С++ Функциональные адаптеры std::bind1st и ваш собственный функтор Явно определяем типы #include <iostream> #include <functional> #include <vector> #include <algorithm> using std::vector; using std::transform; using std::begin; using std::end; using std::cout; using std::for_each; using std::bind1st; class MyFunctor{ public: typedef int first_argument_type; //задаём типы уже существующим внутри bind1st названиям typedef int second_argument_type; typedef int result_type; int operator() (int x, int y) const { //добавили const return x * y; //умножаем значения } }; int main(){ vector<int> v{1,2,3,4,5}; vector<int> out(v.size()); transform(v.begin(), v.end(), out.begin(), bind1st(MyFunctor(), 4)); for_each(out.begin(), out.end(), [](const int i){ cout << i << '\n';}); //выводим на экран (4,8,12...) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
//Листинг #7.2 С++ Функциональные адаптеры std::bind1st и ваш собственный функтор Явно определяем типы #include <iostream> #include <functional> #include <vector> #include <algorithm> using std::vector; using std::transform; using std::begin; using std::end; using std::cout; using std::for_each; using std::bind1st; class MyFunctor:public binary_function<int,int,int>{ public: int operator() (int x, int y) const { //добавили const return x * y; //умножаем значения } }; int main(){ vector<int> v{1,2,3,4,5}; vector<int> out(v.size()); transform(v.begin(), v.end(), out.begin(), bind1st(MyFunctor(), 4)); for_each(out.begin(), out.end(), [](const int i){ cout << i << '\n';}); //выводим на экран (4,8,12...) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//Листинг #8 С++11 Функциональные адаптеры std::bind #include <iostream> #include <functional> using std::cout; using std::bind; void f(int x, int y){ cout << "x == " << x << '\n'; cout << "y == " << y << '\n'; } int main(){ bind(f, std::placeholders::_1, 5)(10); //x = 10, y = 5 bind(f, std::placeholders::_1, 5)(100); //x = 100, y = 5 } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//Листинг #9.1 С++11 Функциональные адаптеры std::bind #include <iostream> #include <functional> using std::cout; using std::bind; void f(int x, int y){ cout << "x == " << x << '\n'; cout << "y == " << y << '\n'; } int main(){ bind(f, std::placeholders::_2, std::placeholders::_1)(5,10); //вставляем параметры в обратном порядке, как если бы вызвали f(10,5) } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//Листинг #9.2 С++11 Функциональные адаптеры std::bind #include <iostream> #include <functional> using std::cout; using std::bind; void f(int x, int y){ cout << "x == " << x << '\n'; cout << "y == " << y << '\n'; } int main(){ bind(f, std::placeholders::_2, 6)(77); //ошибка } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//Листинг #9.3 С++11 Функциональные адаптеры std::bind #include <iostream> #include <functional> using std::cout; using std::bind; void f(int x, int y){ cout << "x == " << x << '\n'; cout << "y == " << y << '\n'; } int main(){ bind(f, std::placeholders::_2, 6)(77, 555); // то же, что f(555, 6), 77 аргумент-заглушка } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//Листинг #9.4 С++11 Функциональные адаптеры std::bind #include <iostream> #include <functional> using std::cout; using std::bind; void f(int x, int y){ cout << "x == " << x << '\n'; cout << "y == " << y << '\n'; } int main(){ auto func = bind(f, std::placeholders::_2, 6); // func(100); //для первого параметра f берём значение из второго, несуществующего, аргумента func func(55,100); //55 значение-заглушка, в параметры сначала возмётся аргумент 100, а потом допишется 6 } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <iostream> #include <functional> using std::cout; using std::bind1st; using std::bind2nd; using std::binary_function; struct f:binary_function<int,int,int>{ int operator() (int x, int y) const{ //функтор должен принимать два параметра cout << "x == " << x << '\n'; cout << "y == " << y << '\n'; return 0; } }; int main(){ bind1st(f(), 2)(6); //f(2,6) //так вставляем первый аргумент из вызова на место первого параметра при приёме bind2nd(f(), 2)(6); //f(6,2) //так вставляем первый аргумент из вызова на место второго параметра при приёме } |
Добавить комментарий