我有以下示例:
struct Wrapper
{
virtual ~Wrapper()
{
}
template <typename U>
WrapperT<U> * clone()
{
return new WrapperT<U>(value); //will not work, because value is not known here
}
};
template <typename T>
struct WrapperT : Wrapper
{
explicit WrapperT(T v)
{
value = v;
}
T value;
};
我想要这样的事情:
Wrapper *t = new WrapperT<int>(1);
WrapperT<double> *t2 = t->clone<double>();
我知道虚拟模板不可用。有什么想法吗?
答案 0 :(得分:0)
一种可能的方法是定义访问者模式,但如果您想支持许多不同的包装类型(即,它不仅仅是一个小子集),实现访问者的成本可能会很高。
你会得到的另一个问题是转换将(必须)动态调度,因此它们可能在运行时失败,你必须提供检测它的机制并对其采取行动(想到异常)。没什么可怕的......
答案 1 :(得分:0)
我建议的解决方案是使用“中性类型”动态制作(如DavidRodríguez - dribeas所说)类型转换。
优势:
缺点
代码:
struct Wrapper
{
// get the "neutral type" value
virtual string getValue() const = 0;
template <typename U> Wrapper* clone() const;
};
template <typename T>
struct WrapperT: Wrapper
{
explicit WrapperT(T v): value(v)
{
}
virtual string getValue() const
{
// use streams to conversion to neutral value, but
// other better method would be suitable
ostringstream strm;
strm << value;
return strm.str();
}
T value;
};
template <typename U> Wrapper* Wrapper::clone() const {
U value;
istringstream strm(getValue());
strm >> value;
return new WrapperT<U>(value);
}
修改强>
要获得更好的效果解决方案,如果只使用数字类型,我们可以将string
改为long double
作为“中性类型”:
template <typename T>
double long WrapperT<T>::getValue() const
{
return value;
}
template <typename U> Wrapper* Wrapper::clone() const {
return new WrapperT<U>(getValue());
}
当只使用整数类型时,我们是否要避免浮点转换的积分?在这种情况下,解决方案会更复杂一些:
getValue()
虚函数,一个用于积分,另一个用于浮点,clone()
函数中,根据getValue()
模板参数类型(目标类型)选择所需的U
函数。