zoukankan      html  css  js  c++  java
  • (原创)c++11中 function/lamda的链式调用

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

    int wmain()
    {
        auto t = create_task([]() -> int
        { 
            return 0;
        });
    
        // Create a lambda that increments its input value.
        auto increment = [](int n) { return n + 1; };
    
        // 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+1;}).then([](int a){return i+2;}).then([](int a){return i+3;}).run(1);
      //result 7
    }

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

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

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

  • 相关阅读:
    STL 算法 std::min
    SAP UI5 初学者教程之五:视图控制器初探 试读版
    SAP UI5 的初始化过程
    Angular 应用里的摇树优化
    Angular 应用里的 vendor.js 是用来干什么的?
    SAP UI5 初学者教程之四:XML 视图初探试读版
    SAP UI5 初学者教程之三:开始接触第一个 SAP UI5 控件 试读版
    SAP UI5 初学者教程之二:SAP UI5 的引导过程(Bootstrap) 试读版
    SAP UI5 初学者教程之一:Hello World 试读版
    SAP UI5 初学者教程的学习目录
  • 原文地址:https://www.cnblogs.com/qicosmos/p/3521647.html
Copyright © 2011-2022 走看看