Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;双调度与运行时多态性?_C++_C++14_Double Dispatch - Fatal编程技术网

C++ C++;双调度与运行时多态性?

C++ C++;双调度与运行时多态性?,c++,c++14,double-dispatch,C++,C++14,Double Dispatch,是否可以使用运行时多态性执行双重分派 假设我有一些类,其中一些类可以被添加/乘以/等等,我想在运行时执行类型擦除的另一个类中动态存储这些类。然后说我想对该类中保存的数据执行基本操作 处理这个问题的方法(据我所知)是使用双重分派来专门化操作。然而,我遇到的所有解决方案都依赖于这样一个事实,即您有大量的类型,然后使用虚拟函数调用或动态\u casts、if-else和RTTI在运行时推断类型。因为类中保存的数据在运行时之前是未知的,所以我无法创建一组虚拟方法或对类型进行暴力检查。所以我认为访问者模式

是否可以使用运行时多态性执行双重分派

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


处理这个问题的方法(据我所知)是使用双重分派来专门化操作。然而,我遇到的所有解决方案都依赖于这样一个事实,即您有大量的类型,然后使用虚拟函数调用或
动态\u cast
s、
if-else
和RTTI在运行时推断类型。因为类中保存的数据在运行时之前是未知的,所以我无法创建一组虚拟方法或对类型进行暴力检查。所以我认为访问者模式是最好的解决方案,但即便如此,我似乎也不知道这是否可行

我有一个包装器类,它持有一个指向嵌套多态类的智能指针,以实现类型擦除和运行时多态性,但我不知道是否可以使用访问者模式对此进行双重分派

请注意,下面的代码是不完整的,它只是显示了我的思维过程

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)) {}
};
无法接受
包装
并拉出类型(由于类型擦除)。但是,我可以将
包装器
插入
Add
expression类,这意味着我可以携带隐藏类型。问题是当我真正开始评估像
Add
这样的结果时。为了知道结果是什么,我需要弄清楚里面到底是什么,或者按照双重调度的思路做点什么


主要的问题是,最符合我的问题的双重分派示例依赖于这样一个事实,即我可以写出所有类,例如
形状
矩形
。由于我不能明确地做到这一点,我想知道是否有一种方法可以执行双重分派,根据上面
模型
类中保存的数据来计算表达式。

听起来您可能想要像
std::any
这样的东西,您可以将任何东西塞进其中,但是您的“访问者”“因为类中保存的数据直到运行时才知道,”为什么在编译时不知道所有可能类型的数据集?这是有答案的,但这个答案的确切、实际和具体细节在你需要做的事情上可能会有巨大的、令人惊讶的差异。或者,简而言之,你试图用抽象的术语来描述一个问题,而这些术语并没有很好地映射到解决方案空间。你需要更加具体,这样才能为具体问题生成解决方案,而不是抽象地谈论一组问题,这些问题的解决方案从“简单”到“困难”,而没有词汇来区分这两种问题@Yakk AdamNevraumont,我很可能使用了不正确或不精确的术语。我不是专家。因此,我将试图澄清我的说法,我希望在type erasure类中存储一个模板类,这就是为什么我声称我不知道可以进入包装器的所有类型。@adam,在任何固定程序中,你都知道传递给模板的每种类型;你到底会不会把所有的类型都用刀子扎?Sexond,请去掉这个抽象概念。你想要一个多态值类型,对吗?您希望支持
c=a+b
,其中
c
必须存储在
a
b
中添加类型的结果?或者我在你的抽象中遗漏了什么?听起来你可能想要像
std::any
这样的东西,你可以把任何东西塞进其中,但是你的“访问者”需要确切地知道他们希望访问的类型。“因为类中保存的数据直到运行时才知道,”为什么在编译时不知道所有可能类型的数据集?这是有答案的,但这个答案的确切、实际和具体细节在你需要做的事情上可能会有巨大的、令人惊讶的差异。或者,简而言之,你试图用抽象的术语来描述一个问题,而这些术语并没有很好地映射到解决方案空间。你需要更加具体,这样才能为具体问题生成解决方案,而不是抽象地谈论一组问题,这些问题的解决方案从“简单”到“困难”,而没有词汇来区分这两种问题@Yakk AdamNevraumont,我很可能使用了不正确或不精确的术语。我不是专家。因此,我将试图澄清我的说法,我希望在type erasure类中存储一个模板类,这就是为什么我声称我不知道可以进入包装器的所有类型。@adam,在任何固定程序中,你都知道传递给模板的每种类型;你到底会不会把所有的类型都用刀子扎?Sexond,请去掉这个抽象概念。你想要一个多态值类型,对吗?您希望支持
c=a+b
,其中
c
必须存储在
a
b
中添加类型的结果?还是我在你的抽象中遗漏了什么?
template<typename T1, typename T2>
const Add<T1, T2> operator+(const T1 &lhs, const T2 &rhs)
{ return Add<T1, T2>(lhs, rhs); }