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

unj*_*nj2 59 c++ rust

Dave Herman最近在Rust 的演讲中说他们从C++借用了这个属性.我无法找到有关该主题的任何内容.有人可以解释一下单态意味着什么吗?

Nik*_*kis 103

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

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

然后我调用这个函数两次:

first((1, 2));
first(("a", "b"));
Run Code Online (Sandbox Code Playgroud)

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

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

  • @Tshepang不是,它更像是C++模板和Java泛型之间的区别. (5认同)
  • 它是*静态调度*的另一个名称吗? (3认同)
  • (续)Rust 和 C++ 使用“专业化”来单态化参数多态性,正如已接受的答案所讨论的那样,并且默认情况下使用静态分派来单态化临时多态性。它们还允许您使用 Rust 中的 [`dyn`](https://doc.rust-lang.org/std/keyword.dyn.html) 或 C++ 中的虚拟方法来选择动态调度。相比之下,Java 对所有事物都使用动态分派,甚至包括泛型(又名参数多态性)。 (2认同)

小智 6

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

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

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

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

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

let integer = Some(5);
let float = Some(5.0);
Run Code Online (Sandbox Code Playgroud)

当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);
}
Run Code Online (Sandbox Code Playgroud)

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

  • 欢迎使用 Stack Overflow 并感谢您的回答。在提供主要由链接组成的答案时,简要总结链接文章的内容通常会有所帮助。这样,如果链接断开,您的帖子仍然有用。您也更有可能以这种方式获得对您的回答的支持。 (3认同)
  • “无成本抽象”是一个非常值得怀疑的表征;程序的较大二进制大小和编译所需的时间会带来成本。 (2认同)

Pot*_*ter 5

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

Herman可能已经创造了一个类似于模板特化的术语,它可以生成与模板相互无关(非多态或"单态")的类型/对象,这是一种多态结构.


wol*_*anh 5

Rust Book中有关于单态化的很好的解释

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

从书中的示例来看,如果您使用以下命令定义了变量Some

let integer = Some(5);
let float = Some(5.0);
Run Code Online (Sandbox Code Playgroud)

当 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);
}
Run Code Online (Sandbox Code Playgroud)