C++模板和Java/C#泛型之间有什么区别?有什么限制?

Quo*_*nux 6 c# c++ java generics template-meta-programming

我从这里读了一篇有趣的文章/主题/讨论,我得到了以下问题:

  • Java/C#泛型有哪些局限性?
  • 使用Java/C#泛型不可能使用C++模板有什么可能?

编辑1 Eric Lippert提出的更多推荐问题

  • 使用C#泛型可以实现哪些模式但使用C++模板却无法实现?
  • C#的真正泛型类型和Java的类型擦除泛型类型有什么区别?

Eri*_*ert 9

首先,您可能想阅读我关于这个主题的2009年文章.

我认为C++模板和C#泛型之间的主要区别在于C++模板实际上在构造模板时完全重新编译代码.C++方法的优点和缺点很多:

  • PRO:您可以有效地创建约束,例如"类型参数T必须具有加法运算符"; 如果代码包含几个相互添加的Ts,那么如果使用不允许添加的类型参数构造模板,则模板将无法编译.

  • CON:您可能会意外地创建未记录的约束,例如"类型参数T必须具有加法运算符".

在C#中你必须说出哪些约束对用户有帮助,但是你只能受限于一小部分可能的约束:接口,基类,值与引用类型和默认构造函数约束,这就是全部.

  • PRO:对于两种不同的结构,语义分析可以完全不同.如果你想要,那真是太棒了.

  • CON:对于两种不同的结构,语义分析可以完全不同.如果你不想那样,这就是等待发生的错误.

在C#中,语义分析无论构造类型多少次都会完成一次,因此需要使用满足约束的任何类型参数,而不仅仅是实际提供的类型参数.

  • PRO:您只生成所需构造的代码.

  • CON:您为所使用的所有构造生成代码.

模板可能会导致codegen变大.在C#中,一般类型的IL生成一次,然后在运行时抖动为您的程序使用的所有类型执行codegen.这具有较小的性能成本,但由于抖动实际上仅为所有引用类型参数生成一次代码,因此可以稍微减轻它.所以如果你有List<object>,List<string>然后jitted代码只生成一次并用于两者.List<int>List<short>通过对比两次代码.

  • PRO:当您使用模板库时,您就拥有源代码.

  • CON:要使用模板库,您必须拥有源代码.

在C#中,泛型类型是一流类型.如果将它们粘贴在库中,则可以在任何地方使用该库,而无需提供源代码.

最后:

  • PRO:模板允许模板元编程.

  • CON:新手很难理解模板元编程.

  • CON:模板系统实际上不允许在通用系统中非常简单的某些类型拓扑.

例如,我想在C++中很难做到这样的事情:

class D<T> 
{
    class S { }
    D<D<T>.S> ds;
}
Run Code Online (Sandbox Code Playgroud)

在C#泛型中,没问题.在运行时,类型仅为所有引用类型参数构建一次.

但是在C++模板中,当你拥有什么时会发生什么D<int>?内部类型构造一个类型的字段D<D<int>.S>,因此我们需要构造该类型.但是那种类型构造了一个类型的字段D<D<D<int>.S>.S>......等等到无穷大.

  • 您可能想要明确表示所有"专业"项目都是"优势C++",即使上一段谈到C#也是如此.值得一提的另一件事是C#期望在一个框架上运行,在该框架中,所有类对象实例都具有单个运行时类型,该类型独立于对它的引用的编译时类型,并且可以创建类型描述符运行.在.net中有可能编写代码 - 没有Reflection - 将采用任意字符串并生成泛型类的实例,其中静态成员将返回该字符串. (2认同)