2011-01-19 101 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. 

实现这些数字操作就留给读者做练习。