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); }