Rust 引用没有实现 Eq/Hash?如何使用它们作为哈希映射键?

Hei*_*nzi 6 object-identity rust

我想构建一个哈希图,其中键是引用。我希望这些引用的相等意味着引用相等,即两个引用借用同一个对象。

use std::collections::hash_map::HashMap;

struct SomeKey();
struct SomeValue();

fn main() {
    let m = HashMap::<&SomeKey, SomeValue>::new();
    
    let t = SomeKey();
    m.get(&t);
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这失败了,编译器告诉我&SomeKey没有实现Hash/ Eq

error[E0599]: the method `get` exists for struct `HashMap<&SomeKey, SomeValue>`, but its trait bounds were not satisfied
  --> src/main.rs:10:7
   |
10 |     m.get(&t);
   |       ^^^ method cannot be called on `HashMap<&SomeKey, SomeValue>` due to unsatisfied trait bounds
   |
   = note: the following trait bounds were not satisfied:
           `&SomeKey: Eq`
           `&SomeKey: Hash`
Run Code Online (Sandbox Code Playgroud)

(操场)

我注意到,如果我实现Eq+Hashfor SomeKey,那么它就可以工作,但这可能会使用底层对象相等性,但这不是我想要的。

有没有办法可以根据指针相等性使用引用作为哈希映射键?

Joh*_*ica 6

你可以使用by_address板条箱。它包装任何指针/引用类型以通过地址而不是内容来比较对象。

use std::collections::hash_map::HashMap;

use by_address::ByAddress;

struct SomeKey();
struct SomeValue();

fn main() {
    let mut m = HashMap::<ByAddress<&SomeKey>, SomeValue>::new();

    let t1 = SomeKey();
    let t2 = SomeKey();

    m.insert(ByAddress(&t1), SomeValue());
    assert!(m.get(&ByAddress(&t1)).is_some());
    assert!(m.get(&ByAddress(&t2)).is_none());
}
Run Code Online (Sandbox Code Playgroud)