2013-06-21 58 views
2

我有下面的例子:如何转换模板类?

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

如果有人在下一行“t->克隆()',你希望发生什么? (其中'foo'是完全不相关的类型) – Yakk

+1

转换指导者模板显式WrapperT(const WrapperT &);'? – jrok

+0

@jrok:构造函数不知道真实类型。他想从一个指针转换为基类到派生类型。 –

回答

0

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

你会得到的另一个问题是,转换将会(必须)被动态分派,所以它们可能会在运行时失败,并且你将不得不提供机制来检测它并采取相应的行动(异常出现) 。没有什么可怕的......

+0

我这个模式不适合我的应用程序。我想转换编译器支持的所有可能的类型。 –

+0

@SteffenRoeber:问题在于当你传递的元素是基类型时,你将丢失类型信息。为了能够恢复该类型信息,您需要在运行时使用动态分派,但完全*通用*解决方案需要模板和静态分派(即让编译器生成您需要的一段代码)。您需要找到不同的设计。 –

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

编辑:

为了更好的性能解决方案,如果只使用数字类型,我们可以通过long double为 “中立型” 转变string

template <typename T> 
double long WrapperT<T>::getValue() const 
{ 
    return value; 
} 

template <typename U> Wrapper* Wrapper::clone() const { 
    return new WrapperT<U>(getValue()); 
} 

我们是否想避免积分浮动仅使用整数类型时的点转换?在这种情况下,该解决方案将是复杂一点:

  • clone()功能取决于U模板创建两个getValue()虚拟函数,一个用于积分和另一个用于浮点,
  • 选择所需getValue()功能参数类型(目标类型)。
+0

我需要一个高性能的解决方案。流媒体是我认为的选择。 –

+0

我读了一些关于蹦床功能的东西。但如果他们适合在这里我不知道。 –

+0

@SteffenRoeber:您可以创建自己的转换功能。如果您始终使用数字类型,则可以将其转换为浮点类型('double'或'long double')作为中性类型。 – Gonmator