具有运行时多态性的C ++双调度吗?

时间:2019-02-17 00:09:27

标签: c++ c++14 double-dispatch

是否可以通过运行时多态执行双重调度?

说我有一些类,其中一些类可以加/乘/等等,我想将那些动态存储在另一个在运行时执行类型擦除的类中。然后说我想对该类中保存的数据执行基本操作。

(据我所知)处理此问题的方法是使用双重分派来专门化操作。但是,我遇到的所有解决方案都依赖于这样的事实,即您有许多类型,然后使用虚拟函数调用或dynamic_castif-else和RTTI在运行时推断类型。因为直到运行时才知道类中保存的数据,所以我无法创建一堆虚拟方法或对类型进行强力检查。因此,我认为访问者模式将是最好的解决方案,但是即使那样,我似乎也无法确定这是否可行。

我有一个包装器类,其中包含一个指向嵌套多态类的智能指针,以实现类型擦除和运行时多态性,但是我不知道是否可以使用访问者模式对此进行双重调度。 / p>

请注意,下面的代码不完整,仅显示了我的思考过程。

class Wrapper {
private:
  class Concept;
  template<typename T> class Model;

  class BaseVisitor {
  public:
    virtual ~Visitor() = default;
    virtual void visit(Concept &) = 0;
  };

  template<typename T>
  class Visitor : public BaseVisitor {
  private:
    T first_;
  public:
    Visitor(T first) : first_(first) {}

    virtual void visit(Concept &other) override {
      // perform addition
    }
  };

  class Concept {
  public:
    virtual ~Concept() = default;

    virtual void add(Concept &m) const = 0;
    virtual void accept(BaseVisitor &visitor) const = 0;
  };

  template<typename T>
  class Model final : public Concept {
  private:
    T data_;

  public:
    Model(T m)
        : data_(m) {}

    virtual void add(Concept &m) const override {
      Visitor<T> v(data_);
      m.accept(v);
    };
    virtual void accept(BaseVisitor &visitor) const override {
      visitor.visit(*this);
    };
  };

  std::shared_ptr<const Concept> ptr_;

  // This isn't right, it just illustrates what I'm trying to do.
  // friend Something operator+(Wrapper &lhs, Wrapper &rhs) {
  //   return (*lhs.ptr_).add(*rhs.ptr_);
  // }

public:
  template<typename T>
  Wrapper(T value) : ptr_(std::make_shared<Model<T>>(value)) {}
};

我已经研究过使用函数指针,模板专门化和静态类型ID来实现双重分发,但是我似乎无法弄清楚如何使其工作。

这甚至可能吗?


编辑

基于下面的评论,为了更具体并提供更多背景知识,我正在使用模板化类,该类使用模板函数执行基本操作(如加法和乘法)。但是,我也想将那些模板化的类存储在向量中,因此可以擦除类型。现在,如果要在执行类型擦除后对那些类进行操作,则需要某种方式来推断模板化函数的类型。但是,由于我无法轻松地从Wrapper中获取内部保留类型,因此我希望有一种方法可以对Wrapper::Model<T>类中保存的数据调用正确的模板函数,是访问者模式,静态类型ID还是什么。


更具体地说,我正在使用类进行延迟求值和符号计算,这意味着我拥有诸如Number<T>之类的类,可以是Number<int>Number<double>等以及诸如VariableComplex<T>之类的类以及用于各种操作的所有TMP组合,诸如Add<Mul<Variable, Variable>, Number<double>>

我可以在编译时处理所有这些问题,但随后我需要将它们存储在向量中-类似于std::vector<Wrapper> x = {Number<int>, Variable, Add<Number<double>, Variable>};。我对此的最佳猜测是执行类型擦除以将表达式存储在多态Wrapper中。这具有双重职责,可以启用对符号表达式的运行时解析支持。

但是,我编写的用于处理加法的函数,例如

template<typename T1, typename T2>
const Add<T1, T2> operator+(const T1 &lhs, const T2 &rhs)
{ return Add<T1, T2>(lhs, rhs); }

不能接受Wrapper并将其拉出(由于类型擦除)。但是,我可以将Wrapper插入Add表达式类中,这意味着我可以携带隐藏的类型。问题是当我真正开始评估诸如Add<Wrapper, Wrapper>之类的结果时。为了知道结果如何,我需要弄清楚里面到底有什么,或者按照双重调度的方式做些什么。

主要问题是,与我的问题like this question on SO最接近的双重调度示例依赖于这样的事实,即我可以写出所有类,例如Shapes,{{ 1}}。由于我无法明确地执行此操作,因此我想知道是否存在一种方法可以根据上面Rectangles类中保存的数据执行两次分派以评估表达式。

0 个答案:

没有答案