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

标签 c# c++ generics templates

复制

What are the differences between Generics in C# and Java… and Templates in C++?



大家好,
我是经验丰富的 C++ 程序员,但对 C# 很陌生。
这些约束和泛型怎么了?为什么它不像在 C++ 中那样工作,在 C++ 中约束是隐式的并且从你对模板类所做的实例化中派生出来?
为什么微软不让它像在 C++ 中一样工作?

最佳答案

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

C# 泛型和 C++ 模板之间的最大区别确实是 C# 泛型可以更好地进行类型检查。它们总是受到约束,从某种意义上说,它们不允许在定义泛型时未声明有效的操作。 C# 的首席设计师提出了一个原因,因为它会增加隐含约束的复杂性。我不精通 C#,所以我不能在这里进一步讨论。我将讨论 C++ 中的问题以及它们将如何改进,以便人们不会认为 C++ 的东西都是错的。

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

这些隐含的约束在短期内对模板设计者来说很容易,因为他们不必关心在模板界面中声明有效的操作。他们将负担推给了模板的用户——因此用户必须确保他满足所有这些要求。通常情况下,用户尝试看似有效的操作但失败了,编译器会向用户提供数百行关于某些无效语法或未找到名称的错误消息。因为编译器一开始不知道违反了什么约束,它列出了错误位置周围涉及的所有代码路径部分,甚至所有不重要的细节,用户将不得不爬过可怕的错误消息文本。

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

C++ 委员会早就看到需要解决这些问题,很快(可能在明年),C++ 也将有一种方法来说明这种明确的约束(请参阅下面的时间机器注释),如下例所示。

template<typename T> requires VariableType<T>
T f(T a, T b) {
    return a + b; 
}

编译器此时会发出错误信号,因为所写的表达式没有被要求标记为有效。这首先有助于模板的设计者编写更正确的代码,因为代码已经在某种程度上进行了类型检查(以及那里可能的情况)。程序员现在可以说明该要求:
template<typename T> requires VariableType<T> && HasPlus<T, T>
T f(T a, T b) {
    return a + b; 
}

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

C++1x 将需求与类型分离。以上适用于原始类型以及类。从这个意义上说,它们更灵活,但也相当复杂。规定何时和何时满足要求的规则很长......您可以使用新规则说明以下内容:
template<typename T> requires MyCuteType<T>
void f(T t) { *t = 10; }

然后,拨打 fint !只需为 MyCuteType<int> 编写概念图即可。教编译器如何取消引用 int 。在这样的循环中它会变得非常方便:
for_each(0, 100, doSomething());

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

好了,到此为止。我希望我可以向您展示约束模板并不是那么糟糕,但实际上更好,因为类型之间的关系以及模板中对它们的操作现在已经被编译器知道了。我什至没有写过 axioms ,这是C++1x 中的另一个好东西' 的概念。请记住,这是 future 的东西,它还没有出来,但它会在 2010 年左右。然后我们将不得不等待一些编译器来实现所有:)

从“ future ”更新

C++0x 概念没有被纳入草案,但在 2009 年末被否决了。太糟糕了!但也许我们会在下一个 C++ 版本中再次看到它?让我们都充满希望!

关于C# 泛型与 C++ 模板 - 需要澄清约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/740969/

相关文章:

c# - 如何使用泛型类型简化此代码?

typescript - TypeScript 中泛型的不安全隐式转换

c# - IIS StackOverflow 异常

c# - MySql.Data 通过反射

c++ - 如何在构造函数中初始化 const 字段?

c++ - 使用 udl 将通用数字系统转换为十进制

javascript - 使用 typescript 和泛型编写库

c# - Startup.cs 方法 app.MapSignalR() 不在 signalR-2.0 中生成集线器

c# - 从范围引用但未定义的 LambdaExpression 变量

c++ - for循环只循环3次