2

I have following example:

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

and I want something like this:

Wrapper *t = new WrapperT<int>(1);
WrapperT<double> *t2 = t->clone<double>();

I know virtual templates are not available. Any ideas?

4

2 回答 2

0

一种可能的方法是定义访问者模式,但如果您想支持许多不同的包装类型(即,如果它不仅仅是一个小子集),实现访问者的成本可能会很大。

您会遇到的另一个问题是转换将(必须)动态分派,因此它们可能在运行时失败,您必须提供机制来检测并采取行动(想到例外)。没有什么可怕的...

于 2013-06-21T13:52:29.830 回答
0

我提出的解决方案是使用“中性类型”来动态地进行类型转换(正如 David Rodrí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);
}

编辑:

为了获得更好的性能解决方案,如果仅使用数字类型,我们可以将stringa更改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
于 2013-06-21T15:13:01.513 回答