我正在尝试定义一个带有默认类型参数的结构,就像 Vec 在 Rust nightly 中使用其分配器工作一样。但是,正如其他答案和 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.
}
我的问题不是为什么 Foo::new()
不能编译,而是为什么 Vec::new()
仍然可以。如果我删除 Foo::new()
,文件会编译。据我所知,支持分配器的 Vec 的新定义应该已经破坏了几乎所有代码。
理想情况下,答案会指向 rustc 中进行此豁免的代码(如果是的话)。
最佳答案
impl
in which fn new
is defined在 T
上通用, 但不是 A
:
impl<T> Vec<T> {
pub const fn new() -> Self {
// ...
}
}
自 A
默认值为 Global
, 这实现了一个 new
Vec<T, Global>
的函数.它没有实现 new
任何其他分配器的功能。所以Vec::new
将始终创建一个新的 Vec<_, Global>
.
事实A
有一个默认值实际上是相切的;解决 Vec::new
时没有考虑到这一点.
你可以制作Foo
以同样的方式工作:
impl Foo<i32> {
fn new() -> Self {
Foo { x: PhantomData }
}
}
请注意,在本例中为 new
将始终创建一个 Foo<i32>
, 如果你想要一个创建不同类型的 Foo
的函数,您需要创建一个不同名称的函数,就像 Vec
有new_in
用于指定与 Global
不同的分配器.
关于rust - 为什么具有默认值的泛型需要类型注释,而 Vec in nightly 会自动推断其分配器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67949615/