C++的概念和Rust的特征有什么相似之处和不同之处?
在Rust中,抽象的主要工具是特征。在C++中,有两种抽象工具:抽象类和模板。为了摆脱使用模板的一些缺点(例如,难以读取错误消息),C++引入了概念,它们是"named sets of requirements"。
这两个功能似乎非常相似:
- 定义特征/概念是通过列出需求来完成的。
- 两者都可用于绑定/限制泛型/模板类型参数。
- Rust特征和带有概念的C++模板都是单一化的(我知道Rust特征也可以用于动态调度,但那是另一回事)。
但据我所知,也有显著的差异。例如,C++的概念似乎定义了一组必须有效的表达式,而不是列出函数签名。但那里有许多不同和令人困惑的信息(可能是因为概念只出现在C++20中?)。这就是为什么我想知道:C++的概念和Rust的特征到底有什么不同和相似之处?
是否有仅由概念或特征提供的功能?例如,铁锈的相关类型和常量如何?或通过多个特征/概念限制类型?
解决方案
免责声明:我还没有使用过概念,我所知道的所有关于它们的信息都是从各种建议和cp偏好中收集的,所以对这个答案持保留态度。
运行时多态
Rust特征既用于编译时多态,有时也用于运行时多态;概念仅用于编译时多态。
结构与名义。
概念和特征的最大区别在于,概念使用结构类型,而特征使用名义类型:
- 在C++中,类型从不显式满足某个概念;如果恰好满足所有要求,它可能会"意外"满足该概念。
- 在Rust中,特定的语法构造
impl Trait for Type
用于显式指示类型实现了特征。
有许多后果;一般来说,从可维护性的角度来看,名义类型化更好--向特征添加需求--而结构类型化更适合桥接第三方库--库A中的类型可以满足库B中的概念,而它们彼此不知道。
约束
特性是必需的:
- 如果不需要此类型来实现提供方法的特征,则不能对泛型类型的变量调用任何方法。
概念是完全可选的:
- 可以在泛型类型的变量上调用方法,而不需要此类型来满足任何概念,也不需要以任何方式进行约束。
- 可以在满足一个(或多个)概念的泛型类型的变量上调用方法,而无需由任何概念或约束指定该方法。
- 约束(请参阅备注)可以完全是即席的,并且不使用命名概念来指定要求;同样,它们也是完全可选的。
注意:约束由requires
子句引入,并指定临时要求或基于概念的要求。
要求
可表达的要求集不同:
- 概念/约束通过替换工作,因此允许语言的全部范围;要求包括:嵌套类型/常量/变量、方法、字段、能够用作另一个函数/方法的参数、能够用作另一个类型的泛型参数及其组合。
- 相比之下,特征只允许一小部分要求:关联的类型/常量和方法。
重载选择
Rust没有即席重载的概念,重载仅由特征发生,还不可能进行专门化。
C++约束可用于按从最不具体到最具体的顺序对重载进行排序,因此编译器可以自动选择满足要求的最具体的重载。
注意:在此之前,在C++中将使用SFINAE或标记调度来实现选择;需要健美操来处理开放式重载集。
析取
我还不太清楚如何使用此功能。
Rust中的要求机制是纯加法的(合取,又名&&
),相反,在C++中requires
子句可以包含析取(又名||
)。
相关文章