我有一个结构,有两个类型参数,其中一个具有默认类型:
use std::marker::PhantomData;
struct Foo<T, F = ()>(PhantomData<(T, F)>);
impl<T, F> Foo<T, F> {
fn new() -> Self { Self(PhantomData) }
fn foo(&self, _: T) {}
}
let foo = Foo::new();
foo.foo(0u32);
上面的代码导致:
error[E0282]: type annotations needed
--> src/main.rs:17:15
|
17 | let foo = Foo::new();
| --- ^^^^^^^^ cannot infer type for `F`
| |
| consider giving `foo` a type
我不明白为什么这里不使用默认类型。请注意,说let foo: Foo<u32> = Foo::new();
已经有效 - 因此无需指定参数F
。但是为什么要指定T
呢?所以我已经很困惑了。
但后来我想起这一切都适用于HashMap
!它被定义为struct HashMap<K, V, S = RandomState>
.而且我从不需要指定任何东西。例如,这适用于:
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert(0u32, 'x');
(操场上的一切)
为什么Foo
和HashMap
之间的默认类型/推理行为不同?哈希图是否使用了一些编译器魔法?
HashMap::new
是这样定义的:
impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
pub fn new() -> HashMap<K, V, RandomState> {
Default::default()
}
}
RandomState
是为new
S
提供的。对于相同的行为,您的代码将如下所示:
impl<T> Foo<T, ()> {
fn new() -> Self { Self(PhantomData) }
fn foo(&self, _: T) {}
}
操场
注意:Default
可用于自定义BuildHasher
:
impl<K, V, S> Default for HashMap<K, V, S>