为什么在存在类型参数默认值的情况下,"HashMap"和我自己的结构的类型推断行为不同?



我有一个结构,有两个类型参数,其中一个具有默认类型:

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');

(操场上的一切)

为什么FooHashMap之间的默认类型/推理行为不同?哈希图是否使用了一些编译器魔法?

HashMap::new

是这样定义的:

impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
pub fn new() -> HashMap<K, V, RandomState> {
Default::default()
}
}

RandomState是为newS提供的。对于相同的行为,您的代码将如下所示:

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>

相关内容

最新更新