2013-06-21 84 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