如何解决不支持模板化虚拟功能的问题?
我需要创建一个Builder / Command类,该类可以存储模板化的参数,该参数稍后可用于调用方法进行一些处理。
基本上,构建器应该能够存储模板化的值,也许有另一种(更正确的)方式来实现它。
设置所有值后,稍后我想调用一个execute方法,该方法将使用模板化的值来调用内部方法。
class BuilderImpl {
public:
virtual void execute() = 0;
virtual int type() = 0;
private:
// common properties here
};
template <typename T1, typename T2>
class BuilderImpl2: public BuilderImpl {
public:
BuilderImpl2(const T1 &v1, const T2 &v2) : mVar1{v1}, mVar2{v2} {
}
virtual void execute() override {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
virtual int type() override {
return 2;
}
T1 mVar1;
T2 mVar2;
};
template <typename T>
class BuilderImpl1: public BuilderImpl {
public:
typedef BuilderImpl1<T> CLAZZ;
BuilderImpl1(const T &v) : mVar1{v} {
}
virtual void execute() override {
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
virtual int type() override {
return 1;
}
template <typename T2>
std::shared_ptr<BuilderImpl> add(const T2 &v2) {
return std::make_shared<BuilderImpl2<T, T2>>(mVar1, v2);
}
T mVar1;
};
class Builder {
public:
void execute() {
std::cout << __FUNCTION__ << std::endl;
if (mImpl) {
mImpl->execute();
}
}
template <typename T>
void add(const T &v) {
if (!mImpl) {
mImpl = std::make_shared<BuilderImpl1<T>>(v);
} else if (mImpl->type() == 1) {
// How do I update my implementation mImpl to point with an instance of BuilderImpl2, any trick?
//mImpl = std::static_pointer_cast<BuilderImpl1<???>>(mImpl)->add(v);
}
}
protected:
std::shared_ptr<BuilderImpl> mImpl{ nullptr };
};
void templatebuilder() {
Builder builder;
builder.add(10);
builder.add(0.0);
builder.execute();
}
答案 0 :(得分:2)
以自动,可扩展的方式执行此操作不可能:两个翻译单元可以定义类型A
和B
,因此必须构造不可能的类型{{1 }}。 (这与以下事实有关:对于 n 输入类型,您需要 O(n ^ 2)实现。)
因此,您必须明确列出支持至少一侧的类型。最直接的方法是使用BuilderImpl2<A,B>
s的阶梯:
dynamic_cast
(您可以添加一种方便的方法来编写if(const auto p=dynamic_cast<BuilderImpl1<A>>(mImpl.get())) mImpl=p->add(v);
else if(const auto p=…) mImpl=p->add(v);
// …
else die_horribly();
。)使用const auto p=mImpl->cast<A>()
的动态类型进行索引可能有更好的方法,但这是一个单独的问题。
答案 1 :(得分:1)
这是对戴维斯答案的补充。
第typedef BuilderImpl1<T> CLAZZ;
行让您认为您已经习惯Java。 Java和C ++在这里有很大的区别: