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

时间:2013-01-07 03:47:12

标签: c++ rust

Rust中的

Dave Herman's recent talk表示他们从C ++中借用了这个属性。我无法找到有关该主题的任何内容。有人可以解释一下单态意味着什么吗?

4 个答案:

答案 0 :(得分:92)

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

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

然后我将此函数调用两次:

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

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

该名称源自编程语言术语“多态” - 意味着一个可以处理许多类型数据的函数。单形化是从多态到单态代码的转换。

答案 1 :(得分:5)

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

赫尔曼可能已经为模板专业化创造了一个术语,它可以生成与模板相互无关(非多态或“单态”)的类型/对象,这是一种多态结构。

答案 2 :(得分:4)

不确定是否有人还在看这个,但是Rust文档实际上确实提到了它如何通过此过程实现了成本抽象。来自Performance of Code Using Generics

  

您可能想知道,当您   使用通用类型参数。好消息是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的   泛型在运行时非常高效。

答案 3 :(得分:2)

Rust Book

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

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

在书籍示例中,如果您使用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);
}