c++ - 管道类存储具有约束的不同模板

标签 c++ templates generic-programming

我有一个类模板 DataProcessor,它看起来像这样:

struct DataProcessorBase
{
    typedef std::shared_ptr<DataProcessorBase> Ptr;
}; // struct DataProcessorBase

template <class _Input, class _Output>
struct DataProcessor : DataProcessorBase
{
    typedef _Input Input;
    typedef _Output Output;

    virtual Output process(const Input * input) = 0;
}; // struct DataProcessor

我想创建一个管道类,它将多个 DataProcessor 实例连接在一起。这意味着处理器 1 的输出必须与处理器 2 的输入匹配,依此类推。类似于以下内容:

template <class _Input, class _Output>
class Pipeline : DataProcessor<_Input, _Output>
{
public:
    Output process(const Input * input);
private:    
    std::vector<DataProcessorBase::Ptr> _processors;
}; // class Pipeline

template <class _Input, class _Output>
_Output Pipeline<_Input, _Output>::process(const _Input * input)
{
    // this is where I start guessing...
    auto rawPtr = dynamic_cast<DataProcessor<_Input, TYPEOFFIRSTPROCESSORSOUTPUT>*>(_processors[0]);
    assert(rawPtr);
    for (size_t i = 0; i < _processors.size(); ++i)
    {
        ...
    }
}

我可以看出这种实现 Pipeline::process 的方式是不正确的。有人可以指出我正确的方向吗?

最佳答案

解耦输入和输出调用。

数据传入和数据传出应该发生在不同的步骤。然后每个数据消费者都可以知道它需要什么,并为您进行转换(如果出现问题,可能会抛出或标记错误)。

struct processor {
  virtual ~processor () {};
  virtual bool can_read_from( processor const& ) const = 0;
  virtual void read_from( processor& ) = 0;
  virtual bool ready_to_sink() const = 0;
  virtual bool ready_to_source() const = 0;
};
template<class T>
struct sink {
  virtual void operator()( T&& t ) = 0;
  virtual ~sink() {}
};
template<class T>
struct source {
  virtual T operator()() = 0;
  virtual ~source() {}
};
template<class In, class Out, class F>
struct step: processor, sink<In>, source<Out> {
  F f;
  step( F&& fin ):f(std::move(fin)) {}

  step(step&&)=default;
  step(step const&)=default;
  step& operator=(step&&)=default;
  step& operator=(step const&)=default;
  step()=default;

  std::experimental::optional<Out> data;
  virtual void operator()( In&& t ) final override {
    data = f(std::move(t));
  }
  virtual bool ready_to_sink() const {
    return !data;
  }
  virtual Out operator()() final override {
    auto tmp = std::move(data);
    data = {};
    return std::move(*tmp);
  }
  virtual bool ready_to_source() const final override {
    return static_cast<bool>(data);
  }
  virtual bool can_read_from( processor const& o ) final override {
    return dynamic_cast<source<In> const*>(&o);
  }
  virtual void read_from( processor &o ) final override {
    (*this)( dynamic_cast<source<In>&>(o)() );
  }
};
template<class In, class Out>
struct pipe {
  std::shared_ptr<processor> first_step;
  std::vector< std::shared_ptr<processor> > steps;
  pipe(std::shared_ptr<processor> first, std::vector<std::shared_ptr<processor>> rest):
    first_step(first), steps(std::move(rest))
  {}
  Out operator()( In&& in ) {
    (*dynamic_cast<sink<In>*>(steps.first_step.get()))( std::move(in) );
    auto last = first_step;
    for (auto step:steps) {
      step->read_from( *last );
      last = step;
    }
    return (*dynamic_cast<source<Out>*>(last.get())();
  }
};
template<class In, class Out>
struct pipeline:step<In, Out, pipe<In,Out>> {
  pipeline( std::shared_pointer<processor> first, std::vector<std::shared_ptr<processor>> steps ):
    step<In, Out, pipe<In,Out>>({ first, std::move(steps) })
  {}
};

关于c++ - 管道类存储具有约束的不同模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32234662/

相关文章:

模板函数上的 C++ 模板类成员

haskell - Haskell 中的函数类型特化

c++ - 制作一个 Mat 类型对象的数组。输出窗口显示相同的帧

c++:错误:在'class std::result_of<void (*(std::unordered_map

c++ - 将模板类型名添加到两个模板类

c++ - 使用 C++ 作为脚本语言

haskell - 不明确的类型变量

c++ - C++-从派生类中提取模板参数

c++ - 如何正确返回类成员数组作为返回参数

c++ - 使用 string::find 和 string::substr 拆分字符串的函数返回错误的标记