关于链式调用,比较典型的例子是c#中的linq,不过c#中的linq还只是一些特定函数的链式调用。c++中的链式调用更少见因为实现起来比较复杂。c++11支持了lamda和function,在一些延迟计算的场景下,这个链式调用的需求更强烈了。链式调用要实现的目是,将多个函数按照前一个的输出作为下一个输入串起来,然后再推迟到某个时刻计算。c++中,目前看到PPL中有这样的用法。PPL中链式调用的例子:

int wmain()
{
auto t = create_task([]() -> int
{
return ;
}); // Create a lambda that increments its input value.
auto increment = [](int n) { return n + ; }; // Run a chain of continuations and print the result.
int result = t.then(increment).then(increment).then(increment).get();
wcout << result << endl;
} /* Output:
3
*/

  例子中先创建一个task对象,然后连续的调用then函数,其实这个then中的lamda的形参可以是任意类型的,只要保证前一个函数的输出为后一个的输入就行。将这些task串起来之后,最后在需要的时候去计算结果,计算的过程是链式的,从最开始的函数开始计算一直到最后一个得到最终结果。这个task和他的链式调用
过程是很有意思的。不过PPL中的链式调用有一点不太好,就是初始化的task不能有参数,因为wait函数是不能接收参数的。经过一番探索,我觉得用c++11我可以做一个差不多链式调用的task,还可以弥补前面所说PPL task不太好的地方,即可以接收参数。其实关于链式调用的实现我之前有博文做了介绍,有兴趣的童孩点这里。不过我对之前的实现方式不太满意,觉得还是PPL这种链式调用方式更好。好了,下面看看我是如何实现和ppl类似的,可以实现链式调用的task。

template<typename T>
class Task; template<typename R, typename...Args>
class Task<R(Args...)>
{
public:
Task(std::function<R(Args...)>&& f) : m_fn(std::move(f)){}   Task(std::function<R(Args...)>& f) : m_fn(f){}
template<typename... Args> R Run(Args&&... args) { return m_fn(std::forward<Args>(args)...); } template<typename F> auto Then(F& f)->Task<typename std::result_of<F(R)>::type(Args...)> { return Task<typename std::result_of<F(R)>::type(Args...)>([this, &f](Args&&... args){
      return f(m_fn(std::forward<Args>(args)...)); });
} private:
std::function<R(Args...)> m_fn;
};

测试代码:

void TestTask()
{
  Task<int(int)> task = [](int i){return i;};
  auto result = task.then([](int a){return i+;}).then([](int a){return i+;}).then([](int a){return i+;}).run();
  //result 7
}

  可以看到,我的Task调用方式和PPL一致,更棒的是还可以接收参数了。也许有人有点疑惑,链式调用这个东西真的有用吗?至少目前看到PPL和TBB是这样用的,而且他对我的开发来说非常有用,至于我对他的具体应用暂且按下不表,后面就会知道我是如何用它了。

如果你觉得这篇文章对你有用,可以点一下推荐,谢谢。

c++11 boost技术交流群:296561497,欢迎大家来交流技术。

(原创)c++11中 function/lamda的链式调用的更多相关文章

  1. JavaScript设计模式-8.链式调用

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. 关于JavaScript中的setTimeout()链式调用和setInterval()探索

    http://www.cnblogs.com/Wenwang/archive/2012/01/06/2314283.html http://www.cnblogs.com/yangjunhua/arc ...

  3. JavaScript中的链式调用

    链模式 链模式是一种链式调用的方式,准确来说不属于通常定义的设计模式范畴,但链式调用是一种非常有用的代码构建技巧. 描述 链式调用在JavaScript语言中很常见,如jQuery.Promise等, ...

  4. 编程中的链式调用:Scala示例

    编程中的链式调用与Linux Shell 中的管道类似.Linux Shell 中的管道 ,会将管道连接的上一个程序的结果, 传递给管道连接的下一个程序作为参数进行处理,依次串联起N个实用程序形成流水 ...

  5. 疯狂的类构造器Builder模式,链式调用

    疯狂的类构造器 最近栈长在做 Code Review 时,发现一段创建对象的方法: Task task = new Task(112, "紧急任务", "处理一下这个任务 ...

  6. 如何写 JS 的链式调用 ---》JS 设计模式《----方法的链式调用

    1.以$ 函数为例.通常返回一个HTML元素或一个元素集合. 代码如下: function $(){ var elements = []; ;i<arguments.length;i++){ v ...

  7. Swift2.1 语法指南——可空链式调用

    原档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programmi ...

  8. jQuery的XX如何实现?——2.show与链式调用

    往期回顾: jQuery的XX如何实现?——1.框架 -------------------------- 源码链接:内附实例代码 jQuery使用许久了,但是有一些API的实现实在想不通.于是抽空看 ...

  9. js实现方法的链式调用

    假如这里有三个方法:person.unmerried();person.process();person.married();在jQuery中通常的写法是:person.unmerried().pro ...

随机推荐

  1. 转:OGRE场景管理器介绍

    一个场景代表在虚拟世界中显示的物品.场景可以包括静态几何体(比如地形或者室内),模型(比如树.椅子等),光和摄像机.场景有下面种类.室内场景:可能由走廊.有家具的屋子和挂着装饰品的墙组成.室外场景:可 ...

  2. [转载]在VirtualBox中收缩虚拟磁盘映像文件

    原文地址:在VirtualBox中收缩虚拟磁盘映像文件作者:bobby 由于经常要测试一些软件,我在VirtualBox虚拟机中安装了一套Windows.使用过虚拟机的朋友都知道,为了节省硬盘空间,一 ...

  3. hibernate注解note

    @Id标识主键属性 1.hibernate5.2 mysql5.7 不需要实现 serializable也可以? 2.主键255的长度我生成了? @GeneratedValue主键生成策略 1.主键设 ...

  4. NSObject协议中方法:description 和 debugDescription

    description基本概念 1.NSLog(@"%@", objectA);这会自动调用objectA的description方法来输出ObjectA的描述信息. 2.desc ...

  5. 【LeetCode】217. Contains Duplicate (2 solutions)

    Contains Duplicate Given an array of integers, find if the array contains any duplicates. Your funct ...

  6. 【转】Kafka 之 中级

    摘要: Kafka配置介绍,原理介绍及生产者,消费者Java基本使用方法. 1.    配置 Ø  Broker主要配置 参数 默认值 说明(解释) broker.id =0   每一个broker在 ...

  7. 【Algorithm】冒泡排序

    一. 算法描述 冒泡排序思想:依次比较相邻的数据,将小数据放在前,大数据放在后:即第一趟先比较第1个和第2个数,大数在后,小数在前,再比较第2个数与第3个数,大数在后,小数在前,以此类推则将最大的数& ...

  8. Flume与Logstash比较

    Flume与Logstash相比,个人的体会如下: Logstash比较偏重于字段的预处理:而Flume偏重数据的传输: Logstash有几十个插件,配置灵活:FLume则是强调用户的自定义开发(s ...

  9. JAVA环境变量的脚本

    简单的一个脚本,用于自动设置环境变量.把代码拷贝,另存为javaEnv.bat.安装完Java 2 SDK之后,开一个命令行窗口,输入javaEnv java2SDKDir(java2SDKDir是你 ...

  10. 收缩sqlserver事务日志

    若要允许 DBCC SHRINKFILE 命令收缩文件,首先需要通过将数据库恢复模式设置为 SIMPLE 来截断该文件. 示例,收缩数据库abce的事务日志 USE abce; GO -- Trunc ...