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

问题描述 投票:6回答:1

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

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

(Qazxswpoi)

为什么Everything on PlaygroundFoo之间的默认类型/推理行为不同? hashmap是否使用了一些编译魔术?

rust
1个回答
8
投票

HashMap以这种方式定义:

HashMap::new

impl<K: Hash + Eq, V> HashMap<K, V, RandomState> { pub fn new() -> HashMap<K, V, RandomState> { Default::default() } } 是为RandomStateS提供的。对于相同的行为,您的代码看起来像这样:

new

impl<T> Foo<T, ()> { fn new() -> Self { Self(PhantomData) } fn foo(&self, _: T) {} }

注意:Playground可用于自定义Default

BuildHasher
© www.soinside.com 2019 - 2024. All rights reserved.