Neo*_*Neo 4 generics traits rust trait-objects
我正在阅读Trait Objects 需要对象安全,但我不明白泛型类型参数的问题。
使用 trait 时用具体类型参数填充的泛型类型参数也是如此:具体类型成为实现 trait 的类型的一部分。当通过使用 trait 对象忘记类型时,无法知道用什么类型填充泛型类型参数。
我正在尝试编写一个示例,但我无法理解。什么是泛型类型参数?
我试图从一个参数化的 trait 中创建一个 trait 对象,但是一旦参数被赋予了一个具体的值,它就可以正常工作:
trait Creator<T> {
fn create(&self) -> T;
}
struct CreationHouse {
creators: Vec<Box<dyn Creator<u32>>>
}
struct NumCreator { seed: u32 }
impl Creator<u32> for NumCreator {
fn create(&self) -> u32 {
return self.seed;
}
}
fn main() {
let ch = CreationHouse{
creators: vec![Box::new(NumCreator{seed: 3})]
};
}
Run Code Online (Sandbox Code Playgroud)
(编译良好,除了“未使用”警告)
我不明白的是“使用特征时用具体类型参数填充的泛型类型参数”是什么意思,以及泛型类型怎么会丢失(因为特征“携带”它们自己)。如果你能写一个段落中描述的案例的例子,我将不胜感激。
“使用特征时用具体类型参数填充的通用类型参数”是什么意思?
一个不起作用的示例是当类型参数是方法的一部分时:
trait Foo {
fn foo<T>(t: T) {}
}
Run Code Online (Sandbox Code Playgroud)
当函数具有类型参数时,Rust 将为实际调用的每种类型对该函数进行单态化(创建一个新副本)。这与特征对象不兼容,因为 Rust 直到运行时才知道该方法属于哪个 impl。
正如@PeterHall 所提到的,使用泛型方法,特征不能是对象安全的。
事实证明,原因只是一个实现限制。
通过使用虚拟表来实现对 trait 方法正确实现的有效分派,虚拟表本质上是一个指向函数的表。trait 对象中的每个方法都在虚拟表中获得一个插槽来存储一个指向函数的指针。
另一方面,泛型函数或方法根本就不是函数或方法。通过用实际的、具体的参数替换泛型参数,可以根据需要创建任意数量的不同函数或方法。
这意味着不可能有一个指向函数的指针,fn foo<T>() -> T;因为它没有代码,相反,你可能有一个指向函数的指针fn foo<i32>() -> i32,一个指向函数的指针,另一个指向函数的指针,另一个指向函数fn foo<String>() -> String。 ..
泛型方法不可能有一个函数指针,因此也有一个 v 表条目,这使得无法通过运行时分派调用该方法,即在dyn Trait.
值得注意的是,出于同样的原因,其他语言也受到同样的限制;例如,C++ 也不能有模板虚方法。
| 归档时间: |
|
| 查看次数: |
990 次 |
| 最近记录: |