2011-06-18 193 views
1

如果我有一類叫做Tuple<T, SIZE>,我想,讓我們說,編譯庫時(使用戶不會遇到鏈接錯誤)實例20個不同的浮動模板:實例化多個模板

template Tuple<float, 1>; 
template Tuple<float, 2>; 
... 
template Tuple<float, 20>; 

有任何方式遞歸執行上述?也許允許它是靈活的,以便我可以把它放在我想要的任何數字,併爲我實例化類?

編輯:(似乎不工作)我迄今爲止嘗試:

template <typename T, unsigned int MAX_RANGE> 
class AllTuples 
{ 
    Tuple<T, MAX_RANGE> y; 
    AllTuples<T, MAX_RANGE - 1> x; 
}; 

template <typename T> 
class AllTuples<T, 1> 
{ 
    Tuple<T, 1> x; 
}; 
AllTuples<float, 10>; 
+1

'AllTuples :: x'也應該是'AllTuples',而不是'Tuple'。 – Xeo

+0

@Xeo:謝謝你指出,固定(雖然仍不能解決原來的問題) – Samaursa

回答

4

對不起你的運氣了。除非使用預處理器元編程庫(boost.pp),否則無法將其自動化。不適用於模板元編程。

你在那裏製作的是隱式實例化Tuple<float, N>。但是隱式實例與外部實例有兩個重要的區別

  1. 它們不會實例化所有成員定義(只有那些立即需要的實例)。其他定義僅在使用時才實例化。
  2. 已使用成員定義的隱式實例化不能用作其他翻譯單元的定義源。

對於後者,由於我不知道原因,我只會引用規範。

非導出的模板必須在每個翻譯單元,其中它是隱式實例化(14.7.1)來定義,除非相應的專業化明確實例化(14.7.2)在一些翻譯單元;不需要診斷。

這可能與鏈接器的複雜性有關,因爲同一模板的隱式實例可能在多個翻譯單元中出現多次,所以需要特殊處理。顯式實例化和非內聯函數不能。

+0

''這可能與鏈接器的複雜性有關,因爲同一個模板的隱式實例可能在多個翻譯單元中出現多次,所以它們需要特殊的處理,顯式實例化和非內聯函數不能。「'爲什麼在'Tuple.cpp'中鍵入'template Tuple ',可以在多個翻譯單元中使用,而不會出現鏈接錯誤?請原諒我缺乏知識,因爲我對模板比較陌生。 – Samaursa

+0

@Samaursa如果你在'Tuple.cpp'和'List.cpp'中鍵入'template Tuple ;',那麼你的程序不合格(不需要診斷)。對於給定的類,顯式實例化只能出現一次。據我瞭解,明確實例化的函數在GCC上有很強的連接,所以這樣一個不合格的程序會產生鏈接錯誤,因爲兩個強連接符號不能連接在一起。隱式實例化的函數具有弱連接性,這意味着編譯器將丟棄除它們中的一個版本以外的所有其他所有函數。 –

+0

我可能誤解了你的評論。我不是在'List.cpp'中輸入它......?我目前正在做的是這裏所建議的:http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13。問題中提到的問題是我有很多'模板元組'我想要支持的最大範圍,並且我想盡可能避免輸入所有這些。 – Samaursa

1

你可以使用一些模板魔法來迫使該實例:

namespace { 
    template <unsigned N> 
    struct Instantiator { 
     void instantiate_members(const Tuple<float,N>& tuple, Instantiator<N-1>) { 
      // use **all** member functions here 
      // so that they get instantiated 
     } 

    template <> 
    struct Instantiator<0> {} 
} 

然後實例化這個模板:

template class Instantiator<20>; 

不幸的是,這不是在維護方面好,因爲你需要保持instantiate_members函數是最新的。您需要確保全部成員被調用,包括所有各種重載。

+0

+1不錯,雖然我仍然不同意這樣做的原因 –

+1

這將實例化類,但不是成員方法 –

+0

@DavidRodríguez - dribeas:這確實是什麼情況,爲什麼它不工作爲了我。 – Samaursa

0

避免模板鏈接錯誤的正確方法是將模板定義放置在您使用它們的每個TU中。通常,頭文件最適合於此目的。使用這樣的顯式實例最多是半有效的,最壞的情況是該死的混淆。

+0

我同意,不幸的是我有我強制要求我不能發佈源代碼:( – Samaursa

+0

@Samarusa:一小部分代碼生成可能在這裏工作,我認爲你的makefile中的三行bash腳本會生成一個頭文件文件包含第一個代碼塊,對於你選擇的任何數字,但是你肯定會有可移植性問題 –

+0

@Samaursa:源代碼是可以簡單分解的 –