我有一个非模板类NC和一个派生模板类TC。我想将指向NC的指针(可能是指向TC实例的指针)转换为TC指针。模板的实际类型仅限于bool,int和字符串。
class NC {
...
}
template <typename T>
class TC: public NC {
private:
T value;
public:
...
void setValue(T value) {
this->value = value;
}
}
class UserValueProvider {
public:
int getValue() const { return 5; }
bool getValue() const { return true; }
string getValue() const { return "foobar"; }
}
void setUserValue(UserValueProvider *uvp, NC *obj) {
auto tobj = dynamic_cast< ? >(obj); // what goes here?
if(tobj)
tobj->setValue(uvp->getValue());
}
显而易见的解决方案是执行3个动态转换(用于int,bool和string)并调用专用实例的setValue。但是我不知道是否会有另一种解决方案,因为更多的专业化可能会需要更动态的转换,并且更有可能忘记一个专业化。
这里的一种解决方案是翻转调用,并使用虚函数。但是首先,让我们重写UserValueProvider::getValue
,因为禁止仅在返回类型上重载。
class UserValueProvider {
template <class T> struct tag { };
int getValue(tag<int>) const { return 5; }
bool getValue(tag<bool>) const { return true; }
std::string getValue(tag<std::string>) const { return "foobar"; }
public:
template <class T>
T getValue() const {
return getValue(tag<T>{});
}
};
现在我们可以调用uvp.getValue<T>()
获得相应的值。接下来,向NC
及其派生类添加一个虚函数:
class NC {
public:
virtual void setValueFrom(UserValueProvider &uvp) = 0;
};
template <typename T>
class TC: public NC {
private:
T value;
public:
void setValue(T value) {
this->value = value;
}
void setValueFrom(UserValueProvider &uvp) override {
setValue(uvp.getValue<T>());
}
};
而且,您只需将UserValueProvider
传递给您经过类型删除的NC
,它将正确分派。
void setUserValue(UserValueProvider *uvp, NC *obj) {
obj->setValueFrom(*uvp);
}