lambda 表达式的应用场景
1、延迟调用
2、链式调用
3、声明式编程,减少函数定义。
链式调用
1、递归,先执行最开始的代码。套娃,没添加一个then 就套一层。执行过程是,先执行m_fun, 然后在执行fun;
2、class Task<R(Args…)> ,类型推导,将类型拆分成2部分
3、R run(Args&&… args) ,加万能引用
4、m_fun(std::forward(args)…); 使用forward 进行完美转发
/**
* lambda 的demo
*
* 田志泽 Tian zhize
* tianzhize137@163.com
*
* 优点:
* 1、声明式编程,更加简洁
* 2、减少了函数的定义,免除了大量函数的维护,提高了可读性
*
*/
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
/**
* 推导返回值类型
* 1、lambda 表达式的默认是const
* 2、没有捕获变量的可以赋值函数指针,捕获的不可以
*/
void typeDeduction() {
auto f = [](int a) { return a + 1; }; //可以推导返回值类型
// auto f1 = [](int a) { return {1,1};}//无法推导
// 1、lambda 表达式的默认是const
int a = 0;
auto f1 = [=]() mutable { return a++; };
// mutable 可以修改外部捕获变量
// auto f2 = [=]() {
// return a++;
// };
//结合std::funtion 和 bind
std::function<int(int)> func1 = [=](int c) { return a + c; };
std::function<int()> func2 = std::bind([](int a) { return a; }, 10);
std::function<int()> func3 = std::bind(func1, 10);
// 2、没有捕获变量的可以赋值函数指针,捕获的不可以
typedef void (*Ptr)();
Ptr p = []() {};
// Ptr p1 = [=](){};
}
/**
* 声明式编程,更加简洁,改动量很小
*/
void decl() {
std::vector<int> vec;
for_each(vec.begin(), vec.end(), [](int a) {
//处理
});
// 查找大于5 小于 10
// 如果没有返回值接收,会报错ignoring return value of function declared with warn_unused_result attribute
int count = std::count_if(vec.begin(), vec.end(), [](int a) -> bool {
bool b = a > 5 && a <= 10;
return b;
});
}
/**
* 链式调用
* 1、采用递归的方式,压栈
* 2、
*/
#include <functional>
template <class T>
class Task;
template <class R, class... Args>
class Task<R(Args...)> {
public:
Task(std::function<R(Args...)>&& f) : m_fun(f) {
}
Task(std::function<R(Args...)>& f) : m_fun(f) {
}
R run(Args&&... args) {
return m_fun(std::forward<Args>(args)...);
}
template <class F>
Task<typename std::result_of<F(R)>::type(Args...)> then(F&& f) {
//获取返回值
using return_type = typename std::result_of<F(R)>::type;
//
auto fun = std::move(m_fun);
return Task<return_type(Args...)>([fun, &f](Args&&... args) {
//前一个的输出作为下一个输入
auto ret = fun(std::forward<Args>(args)...);
return f(ret);
});
//重新构建一个临时对象,task, 新task 中,新的lambda 表达式是,先执行m_fun. 在执行传入的。
//所以调用的顺序 调用1 - 调用2 ,调用1的返回值作为 调用2的参数。
}
std::function<R(Args...)> m_fun;
};
/**
* 再次编写一次加强记忆
*/
template <class T>
class TaskA;
template <class R, class ...Args>
class TaskA<R(Args...)> {
public:
TaskA(std::function<R(Args...)> &&f) : m_fun(f){}
TaskA(std::function<R(Args...)> &f) : m_fun(f){}
R run(Args...args) {
return m_fun(std::forward<Args>(args)...);
}
template<class F>
auto then(F && f) -> TaskA<typename std::result_of<F(R)>::type(Args...)>{
// 获取F的返回值
using NewType = typename std::result_of<F(R)>::type(Args...);
// 新创建一个task 对象
auto newFun = [&f,this](Args&&...args){
auto ret = m_fun(std::forward<Args>(args)...);
return f(ret);
};
return TaskA<NewType>(newFun);
}
std::function<R(Args...)> m_fun;
};
void test_lambda_task() {
//调用过程 task.then({调用1}).then({调用2}).run(1);
// 套娃,没添加一个then 就套一层。执行过程是,先执行m_fun, 然后在执行fun;
Task<int(int,int)> task{[](int a,int b) {
std::cout << 1 << std::endl;
return a + 1;
}};
auto task1 = task.then([](int a)->double {
std::cout << 2 << std::endl;
return a + 2;
});
auto task2 = task1.then([](double a) {
std::cout << 3 << std::endl;
return a + 2;
});
task2.run(1,2);
}
void test_lambda_taskA() {
//调用过程 task.then({调用1}).then({调用2}).run(1);
// 套娃,没添加一个then 就套一层。执行过程是,先执行m_fun, 然后在执行fun;
TaskA<int(int,int)> task{[](int a,int b) {
std::cout << 1 << std::endl;
return a + 1;
}};
auto task1 = task.then([](int a)->double {
std::cout << 2 << std::endl;
return a + 2;
});
auto task2 = task1.then([](double a) {
std::cout << 3 << std::endl;
return a + 2;
});
task2.run(1,2);
}
int main() {
test_lambda_task();
test_lambda_taskA();
system("pause");
}