c++ - std::functions 的复合模式

标签 c++ c++11 templates variadic-templates composite

我正在尝试为 std::functions 实现一个复合模式使用模板类,其中每个复合类处理其子类的返回值。
所以模式类可能看起来像这样:

class AbstractClass {
  public:
     virtual void process() = 0;
};

template<typename ReturnType>
class PrimitiveClass : public AbstractClass {
  public: 
    ReturnType process() {
       // please note, that the result is not returned by the return statement
       return this->func();  //this is just for simplicity
    }

  private:
    std::function<ReturnType()> func;
}

template<typename ReturnType, typename ...Args>
class CompositeClass : public AbstractClass {
  public:
    ReturnType process() {
      // --> This is where I want to process all children first and then pass their return values to this->func
      // the following code is kind of a pseudo code:
      for(auto it = vector.begin(); it != vector.end(); ++it {
          results.add((**it).process())
      }
      return this->func(results)
    }

  private:
    std::function<ReturnType(Args...)> func;
    std::vector<std::shared_ptr<AbstractClass>> children;
};

例如,我有一个 CompositeClassstd::function<int(int, double, bool)该函数的参数类型也是 ReturnType它的子项。我想将 child 的返回值传递给上述 std::function
任何人都可以想出一种方法,我该如何实现?

最佳答案

如果我明白你想要什么(如果我没有错的话)...

(1)解决process()返回值不协变的问题(请参阅 Igor Tandetnik 的评论)您需要一个模板抽象类来表达正确的返回值;举例说明

template <typename T>
struct abstClass 
 { virtual T process() const = 0; };

(2) 所以你的 CompositeClass (重命名为 nodeClass ,在我的以下示例中)继承自 abstClass<ReturnType>

(3) 你的 PrimitiveClass是无用的,因为您可以将大小写(对不带参数的函数的引用)管理为 CompositeClassArgs

(4) 你需要一个leafClass处理基本值

(5) 在 CompositeClass ( nodeClass ), children , 而不是 std::vectorshared_ptr<AbstractClass> (那不能做你想做的事),可以是一个

std::tuple<std::shared_ptr<abstClass<Args>>...>  children;

鉴于这些要点,我提出以下解决方案(不幸的是,它是 C++14,因为使用从 C++14 开始可用的 std::index_sequencestd::make_index_sequence;但是如果您需要 C++11解决方案,不难为他们写替代品)

#include <tuple>
#include <memory>
#include <iostream>
#include <functional>

template <typename T>
struct abstClass 
 { virtual T process() const = 0; };

template <typename T>
class leafClass : public abstClass<T>
 {
   private:
      T  value;

   public:
      leafClass (T && v0) : value { std::forward<T>(v0) }
       { }

      T process () const
       { return value; };
 };

template <typename RetT, typename ... ArgTs>
class nodeClass : public abstClass<RetT>
 {
   private:
      using funcT = std::function<RetT(ArgTs...)>;

      template <typename T>
      using shrPAC = std::shared_ptr<abstClass<T>>;

      funcT                         func;
      std::tuple<shrPAC<ArgTs>...>  childrens;

      template <std::size_t ... Is>
      RetT processH (std::index_sequence<Is...> const &) const
       { return func(std::get<Is>(childrens)->process()...); }

   public:
      nodeClass (funcT && f0, shrPAC<ArgTs> && ... as)
         : func { std::forward<funcT>(f0) },
           childrens { std::forward<shrPAC<ArgTs>>(as)... }
       { }

      RetT process () const
       { return processH(std::make_index_sequence<sizeof...(ArgTs)>{}); }
 };

int main ()
 {
   auto func0 = [](int i, double d, bool b) { return int( b ? i+d : i-d ); };

   auto shpLci = std::make_shared<leafClass<int>>(1);
   auto shpLcd = std::make_shared<leafClass<double>>(2.2);

   auto shpNb  = std::make_shared<nodeClass<bool>>([](){ return true; });

   auto shpNc0 = std::make_shared<nodeClass<int, int, double, bool>>
      (func0, shpLci, shpLcd, shpNb);
   auto shpNc1 = std::make_shared<nodeClass<int, int, double, bool>>
      (func0, shpNc0, shpLcd, shpNb);
   auto shpNc2 = std::make_shared<nodeClass<int, int, double, bool>>
      (func0, shpNc1, shpLcd, shpNb);

   std::cout << shpNc0->process() << std::endl; // print 3
   std::cout << shpNc1->process() << std::endl; // print 5
   std::cout << shpNc2->process() << std::endl; // print 7
 }

关于c++ - std::functions 的复合模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46377906/

相关文章:

c++ - 合并集合中满足谓词的元素

ruby 模板 : How to pass variables into inlined ERB?

C++ 模板元编程特化歧义

c++ - 无法解析类型 size_t C++ eclipse

c++ - 抑制/删除 Eclipse CDT 中的特定错误

c++ - 不能在 if 语句中直接使用 void func 将字符串转换为大写 - C++

c++ - vector中包含的对象有什么要求

c++ - 通过字符串模板参数访问元组

c++ - 如何正确声明模板类的嵌套类的友元?

C++ 模板显式右值类型