我试图定义一个带有默认类型参数的结构,就像 Vec 每晚在 Rust 中使用它的分配器工作一样。但是,正如其他答案和 Rust 论坛中所解释的,这不是类型推断的工作方式:
use std::marker::PhantomData;
struct Foo<X: Copy = i32> {
x: PhantomData<X>
}
impl<X: Copy> Foo<X> {
fn new() -> Foo<X> {
Foo {
x: PhantomData
}
}
}
fn main() {
// type annotations needed
let foo = Foo::new();
// works??
let mut bar = Vec::new();
bar.push(42); // to let Rust infer T.
}
Run Code Online (Sandbox Code Playgroud)
我的问题不是为什么Foo::new()不编译,而是为什么Vec::new()仍然编译。如果我删除Foo::new(),文件将编译。据我了解,支持分配器的 Vec 的新定义应该已经破坏了几乎所有代码。
理想情况下,一个答案会向我指出 rustc 中的代码,如果它是一个豁免。
定义的impl infn new是泛型 over T,但不是A:
impl<T> Vec<T> {
pub const fn new() -> Self {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
由于A具有默认值Global,因此它实现了一个new函数Vec<T, Global>。它没有new为任何其他分配器实现功能。所以Vec::new总是会创建一个新的Vec<_, Global>.
A具有默认值的事实实际上是相切的;解决时没有考虑到这一点Vec::new。
你可以用Foo同样的方式工作:
impl Foo<i32> {
fn new() -> Self {
Foo { x: PhantomData }
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,在这种情况下,new总是会创建一个Foo<i32>,如果你想创建一个不同类型的功能Foo,你需要创建一个不同名称的功能,就像Vec有new_in用于指定不同的分配比Global。