class Base{
public:
template <typename T> T getValueAs()
{
//should return (T)this->getValue()
}
template <typename T> void setValueFrom(T val)
{
//should call this->setValue((Impl::value_type)val)
}
};
template<typename T> class Impl : public Base {
public:
virtual void setValue(const T& val){ ... }
virtual T getValue() const{ ... }
protected:
T value;
};
//also some very speficic impl would be
class NumVal : public Base<int>{
};
我想使用它作为:
Impl<float> var;
var.setValue(42.0f);
Base* baseVar = (Base*)&var;
int convertedVal = baseVar->getValueAs<int>(); // should return (int)(42.0f)
我知道我们不能重写模板成员函数,这里的限制是Base
类不知道Impl
类的确切值类型,是否有替代方案来实现类似的事情?
否则,我需要在基类上实现非常具体的转换,以便在后代类上重写,例如:
class Base{
public:
virtual std::string getString() = 0;
virtual int getInt() = 0;
virtual bool getBool() = 0;
};
所以我只需要Base::get<T>()
如果您坚持设计,可以在std::any
的帮助下实现。请注意,下面的解决方案不满足此要求:
int convertedVal = baseVar->getValueAs
();//应该返回(int)(42.0度)的
,因为目前我没有看到实现它的方法。
class Base {
public:
template <typename T> T getValueAs() const
{
return std::any_cast<T>(getValueImpl());
}
virtual std::any getValueImpl() const = 0;
}
template<typename T> class Impl : public Base {
public:
std::any getValueImpl() const override { return std::make_any(value); }
protected:
T value;
}
这在运行时是类型安全的——也就是说,如果类型不匹配,将抛出异常。缺点是您将付出双类型擦除的代价(一个在Base
操作中,另一个在std::any
操作中)。