【发布时间】:2016-04-07 15:33:13
【问题描述】:
我为HashMap 使用了一个复杂的密钥,这样该密钥包含两部分,一部分是String,我无法弄清楚如何通过HashMap::get 方法进行查找而不分配每次查找都使用新的String。
这里有一些代码:
#[derive(Debug, Eq, Hash, PartialEq)]
struct Complex {
n: i32,
s: String,
}
impl Complex {
fn new<S: Into<String>>(n: i32, s: S) -> Self {
Complex { n: n, s: s.into() }
}
}
fn main() {
let mut m = std::collections::HashMap::<Complex, i32>::new();
m.insert(Complex::new(42, "foo"), 123);
// OK, but allocates temporary String
assert_eq!(123, *m.get(&Complex::new(42, "foo")).unwrap());
}
问题在于最终断言。它通过了,但它需要临时堆分配,因为如果不构造 String,我就无法构造 Complex。
为了消除这样的临时分配,Rust 提供了 Borrow 特征,HashMap::get 方法利用了它。我了解如何使 Borrow 用于简单的键。例如,Rust 标准库的 PathBuf 通过使用 std::mem::transmute 在底层实现 Borrow<Path>,但我不知道如何使它适用于我的 Complex 类型:
#[derive(Debug)]
struct Borrowable {
// ??? -- What goes here? Perhaps something like:
n: i32,
s1: &str, // ??? -- But what would the lifetime be? Or maybe:
s2: str, // ??? -- But how would I extend this to a complex type
// containing two or more strings?
}
impl Borrowable {
fn new(n: i32, s: &str) -> &Self {
// ??? -- What goes here? It must not allocate.
unimplemented!();
}
}
impl std::borrow::Borrow<Borrowable> for Complex {
fn borrow(&self) -> &Borrowable {
// ??? -- What goes here? How can I transmute a Complex into a
// &Borrowable?
unimplemented!();
}
}
这似乎是一个常见的用例,我怀疑我遗漏了一些关于 Borrow 的重要信息,但我完全不知所措。
【问题讨论】:
标签: rust