C#泛型与C++模板 - 需要澄清约束

use*_*637 11 c# c++ generics templates

重复

C#和Java中的泛型与C++中的模板有什么区别?


大家好,

我是经验丰富的C++程序员,但对C#来说还是个新手.

那些约束和泛型是什么?为什么它不像在C++中那样工作,其中约束是隐式的,并且是从对模板类进行的实例化派生的?

为什么微软没有像C++一样工作?

Joh*_*itb 20

嗯,一般来说,C++模板和C#泛型是相似的 - 与完全不同的Java泛型相比,但它们也有很大的差异.与在C#中一样,通过使用反射来获得运行时支持,获取描述用于实例化泛型的类型的对象.C++没有反射,它在类型上的所有功能都是在编译时完成的.

C#泛型和C++模板之间的最大区别确实是C#泛型是更好的类型检查.它们总是受到约束,因为它们不允许在定义泛型时未被证明有效的操作.C#的首席设计师提出了一个原因,即它可能会带来更多的复杂性.我不熟悉C#,所以我不能在这里进一步讨论.我将讨论C++中的问题以及它们将如何改进,以便人们不认为C++的东西是错的.

在C++中,模板不受约束.如果执行操作,则在模板定义时,暗示操作将在实例化时成功.C++编译器甚至不需要在语法上检查模板的有效性.如果它包含语法错误,则必须在实例化时诊断该错误.之前的任何诊断都是纯粹的实施.

这些隐含约束在短期内对模板设计者来说很容易,因为他们不必关心在模板界面中陈述有效操作.他们将负担放在模板的用户身上 - 因此用户必须确保他满足所有这些要求.通常情况下,用户尝试看似有效的操作但失败了,编译器会向用户提供数百行关于某些无效语法或未找到名称的错误消息.因为编译器无法知道什么样的约束,特别是在第一个地方违反,它列出了有史以来参与各地发生故障代码路径和所有甚至不是重要的细节各地,用户将不得不通过可怕的错误信息抓取文本.

这是一个基本问题,可以通过在模板或泛型的接口处声明类型参数必须具有的属性来解决.据我所知,C#可以约束参数来实现接口或继承基类.它在类型级别上解决了这个问题.

C++委员会长期以来一直认为需要解决这些问题,很快(明年可能),C++也会有一种方式来陈述这样的显式约束(参见下面的时间机器说明),如下例所示.

template<typename T> requires VariableType<T>
T f(T a, T b) {
    return a + b; 
}
Run Code Online (Sandbox Code Playgroud)

编译器在该点发出错误信号,因为写入的表达式未被要求标记为有效.这首先有助于模板的设计者编写更正确的代码,因为代码在某种程度上已经过类型检查(很好地在那里可以实现).程序员现在可以说明这个要求:

template<typename T> requires VariableType<T> && HasPlus<T, T>
T f(T a, T b) {
    return a + b; 
}
Run Code Online (Sandbox Code Playgroud)

现在,它将编译.通过看作T出现的返回类型,编译器自动暗示它T是可复制的,因为该使用T出现在接口中,而不是模板体中.其他要求使用要求条款说明.现在,如果用户使用没有op+定义的类型,则会收到相应的错误消息.

C++ 1x将需求与类型分离.以上适用于原始类型以及类.从这个意义上讲,它们更灵活,但相当复杂.说明满足要求的时间和时间的规则很长......您可以使用新规则说明以下内容:

template<typename T> requires MyCuteType<T>
void f(T t) { *t = 10; }
Run Code Online (Sandbox Code Playgroud)

然后,打电话fint!这可以通过编写一个概念图来MyCuteType<int>教导编译器如何取消引用int.它将在这样的循环中变得非常方便:

for_each(0, 100, doSomething());
Run Code Online (Sandbox Code Playgroud)

由于程序员可以告诉编译器一个int如何满足一个概念input iterator,你实际上可以在C++ 1x中编写这样的代码,如果你只编写适当的概念图,那真的不是那么困难.

好的,够了.我希望我能告诉你,模板受限制并不是那么糟糕,但实际上更好,因为编译器现在知道模板之间的关系类型和它们之间的操作.而我甚至没有写过axioms,这是C++1x"概念中的另一个好东西.请记住,这是未来的东西,它还没有出来,但它将大约在2010年.然后我们将不得不等待一些编译器实现所有:)


从"未来"更新

草案中没有接受C++ 0x概念,但是已经在2009年底投票了.太糟糕了!但也许我们会在下一个C++版本中再次看到它?让我们都充满希望!