2011-01-19 100 views
5

我移植一個C++應用程序到C#,並已跨越模板運行。我已經閱讀了一些關於這些的文章,並且我明白一些模板類似於.Net泛型。我讀了SO answer這個案例,很好地總結了它。移植C++到C# - 模板

但是,似乎的C++模板某些用途不直接相關的仿製藥。在以下來自維基百科的Template metaprogramming文章的示例中,模板似乎接受一個值,而不是一個類型。我不太確定這將如何移植到C#?

template <int N> 
struct Factorial 
{ 
    enum { value = N * Factorial<N - 1>::value }; 
}; 

template <> 
struct Factorial<0> 
{ 
    enum { value = 1 }; 
}; 

// Factorial<4>::value == 24 
// Factorial<0>::value == 1 
void foo() 
{ 
    int x = Factorial<4>::value; // == 24 
    int y = Factorial<0>::value; // == 1 
} 

顯然,在這個例子中我可以這樣做:

public int Factorial(int N){ 
    if(N == 0) return 1; 
    return Factorial(N - 1); 
} 

,但這對我來說似乎是一個重構的功能,而不是一個端口,以語義相似的代碼。

+0

爲什麼你會使用經典的遞歸函數作爲c#泛型?嘗試閱讀這篇文章http://msdn.microsoft.com/en-us/library/bb549151.aspx使用Func nemke 2011-01-19 13:37:08

+1

這個問題最有可能不會與常量(類型)作爲模板參數,但與如果目前在您的代碼庫中使用了類或函數的特化和部分特化。沒有一些特定的例子,答案將需要很廣泛,可能不是很有用。由於這個原因,我正在投票結束,隨時添加關於您在轉換時遇到問題的部分代碼的具體問題。 – 2011-01-19 13:38:57

+1

@nemke - 在本例中,Factorial模板在編譯時展開 - 因此在運行時實際上沒有工作。 OP希望移植代碼,而不必將太多的代碼翻譯成不同類型的C#調用 - 所以如果可能的話,更喜歡基於通用的解決方案。不幸的是,事實並非如此。 @David - 非常好的點也 – 2011-01-19 13:40:17

回答

5

不幸的.Net仿製藥只能接受類型。 C++模板採用編譯器認爲是常量表達式的其他值,因爲它們實際上只是擴展爲更多代碼的宏。

這意味着你打開的代碼放到一個方法調用的想法是最好的選擇。你可以把這個方法調用返回一個.Value屬性類型(以下你的例子),從而保持類似模板移植的代碼:

return Factorial(N-1).Value; 
3

看看這篇文章對C#泛型和C++模板之間的差異:

我覺得你的例子包括在那裏。

MSDN Link

1

簡短的回答是,不是一切都可以用C實現++模板可以在C#泛型中完成。在模板接受非類型值的情況下,每種情況都必須根據具體情況進行適當處理和重新考慮。

0

這是接近我能想到的:

public class Factorial<T> 
    where T : IConvertible 
    { 
     public T GetFactorial(T t) 
     { 
      int int32 = Convert.ToInt32(t); 
      if (int32 == 0) 
       return (T) Convert.ChangeType(1, typeof(T)); 
      return GetFactorial((T) Convert.ChangeType(int32-1, typeof(T))); 
     } 
    } 

問題是你不能定義泛型和限制它ValueTypes。這將爲字節的Int16和的Int32工作。也適用於小數值的Int64

5

在下面的例子中...模板似乎接受一個值,而不是一個類型。

這不是你最大的問題。事實上,這在理論上可以通過使用Church numeral或依賴嵌套泛型類型的Peano表示法在C#中解決。

然而,你的問題是,C#不允許模板特。模板專門負責在你的榜樣用於定義的0階乘是1,而不是相同的所有其他號碼。 C#不允許這樣做。

因此,無法在遞歸模板(泛型)定義中指定基本情況,因此無法遞歸。 C#泛型不是圖靈完整的,而C++模板是。


事情是這樣的:

class Zero { } 

class Successor<T> : Zero where T : Zero { } 

// one: 
Successor<Zero> 
// two: 
Successor<Successor<Zero>> 
// etc. 

實現這些數字操作就留給讀者做練習。