什么是C ++上下文的单态化?


Answers:


135

单一化意味着生成通用功能的专用版本。如果我编写了一个提取任何一对第一个元素的函数:

fn first<A, B>(pair: (A, B)) -> A {
    let (a, b) = pair;
    return a;
}

然后我两次调用此函数:

first((1, 2));
first(("a", "b"));

编译器将生成的两个版本first(),一个版本专用于整数对,另一个版本专用于字符串对。

该名称源自编程语言术语“多态性”,即一种可以处理多种类型数据的功能。单态化是从多态代码到单态代码的转换。


它是静态调度的另一个名称吗?
tshepang

9
@Tshepang不是,它更像C ++模板和Java泛型之间的区别。
塔维安·巴恩斯

在我看来,与我们在C ++中简单地称呼(隐式)模板专业化相同。不要与单态相混淆,从通过父接口处理子类型的意义上讲,单态是逻辑上与多态相反的。
stellarpower

17

不确定是否有人还在看这个,但是Rust文档实际上确实提到了它如何通过此过程实现了成本抽象。从使用泛型的代码性能开始

您可能想知道在使用泛型类型参数时是否存在运行时成本。好消息是,Rust以这样的方式实现泛型,即使用泛型类型的代码不会比使用具体类型的代码运行慢。

Rust通过在编译时对使用泛型的代码进行单态化来实现这一点。单色化是通过填充编译时使用的具体类型,将通用代码转换为特定代码的过程。

在此过程中,编译器执行与清单10-5中用于创建泛型函数的步骤相反的操作:编译器查看调用泛型代码的所有位置,并为调用泛型代码的具体类型生成代码。 。

让我们看看使用标准库的Option枚举的示例如何工作:

let integer = Some(5);
let float = Some(5.0);

当Rust编译此代码时,它将执行单态化。在该过程中,编译器读取Option实例中已使用的值,并标识两种Option:一种是i32,另一种是f64。这样,它将Option的通用定义扩展为Option_i32和Option_f64,从而用特定的替换通用定义。

该代码的单色版本如下所示。通用Option替换为编译器创建的特定定义:

// Filename: src/main.rs

enum Option_i32 {
    Some(i32),
    None,
}

enum Option_f64 {
    Some(f64),
    None,
}

fn main() {
    let integer = Option_i32::Some(5);
    let float = Option_f64::Some(5.0);
}

因为Rust将通用代码编译成在每个实例中指定类型的代码,所以我们无需为使用通用而付出任何运行时成本。代码运行时,其性能与我们手工复制每个定义时的性能相同。单态化的过程使Rust的泛型在运行时非常高效。


1
欢迎使用Stack Overflow,感谢您的回答。当提供一个主要由链接组成的请求者时,简要总结链接文章的内容通常会很有帮助。这样,如果链接断开,您的帖子仍然有用。这样您也更有可能对您的答案表示赞同。
新帕戈

4

对此不确定;你可以链接到谈话吗?这可能是一个过分的评论。

Herman可能为模板专业化等术语创造了一个术语,该专业术语从模板(即多态结构)生成相互不相关(非多态或“单态”)的类型/对象。


1

Rust书中有一个很好的关于单态化的解释

单色化是通过填充编译时使用的具体类型,将通用代码转换为特定代码的过程。

在书籍示例中,如果您使用定义了变量Some

let integer = Some(5);
let float = Some(5.0);

当Rust编译此代码时,它将执行单态化。在该过程中,编译器读取Option<T> 实例中使用的值,并标识两种Option<T>:一种是i32,另一种是f64。因此,其膨胀的一般定义Option<T>Option_i32Option_f64,从而与特定的人代替通用定义。

该代码的单色版本如下所示。泛型 Option<T>被编译器创建的特定定义替换:

文件名:src / main.rs

enum Option_i32 {
    Some(i32),
    None,
}

enum Option_f64 {
    Some(f64),
    None,
}

fn main() {
    let integer = Option_i32::Some(5);
    let float = Option_f64::Some(5.0);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.