use std::collections::HashMap;
#[derive(Eq, Hash, PartialEq)]
struct Key<'a> {
key: &'a str,
}
fn get<'m, 'k, 'kr>(map: &'m HashMap<Key, usize>, key: &'k Key<'kr>) -> Option<&'m usize> {
map.get(key)
}
fn main() {
let map: HashMap<Key, usize> = HashMap::new();
get(&map, &Key { key: "foo" });
}
给我以下错误:
error[E0623]: lifetime mismatch
--> src/main.rs:9:5
|
8 | fn get<'m, 'k, 'kr>(map: &'m HashMap<Key, usize>, key: &'k Key<'kr>) -> Option<&'m usize> {
| -------- -----------------
| |
| this parameter and the return type are declared with different lifetimes...
9 | map.get(key)
| ^^^^^^^^^^^^ ...but data from `key` is returned here
是的,key
的生存期与返回类型的生存期不同,但我看不到"此处返回来自key
的数据"......我看到使用密钥返回的map
的数据为..好吧,只是一个返回值后不再需要的键。
IMO,get
应该适用于任何'k
,'kr
传入。返回值生存期应与map
生存期相同。这就是我试图表达的,但显然我的想法在某处是错误的。
您的签名中有两个应该相关的Key
,但您没有关联它们。最简单的解决方案是给它们相同的生命周期:
fn get<'m, 'k>(map: &'m HashMap<Key<'k>, usize>, key: &Key<'k>) -> Option<&'m usize>
// ^^ ^^^^ ^^^^
您的原始代码更接近于此,在生命周期消除之后:
fn get<'m, 'k, 'kr, 'x>(map: &'m HashMap<Key<'x>, usize>, key: &'k Key<'kr>) -> Option<&'m usize>
但是我将改用这种形式:
fn get<'m, 'k1, 'k2>(map: &'m HashMap<Key<'k1>, usize>, key: &Key<'k2>) -> Option<&'m usize>
HashMap::get
有一个不平凡的签名:
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq,
例如,这允许您在具有&String
或&str
的HashMap<String, V>
中查找。
让我们将其移植到我们的代码中,并对泛型类型进行一些替换:
fn get<'m, 'k1, 'k2>(map: &'m HashMap<Key<'k1>, usize>, key: &Key<'k2>) -> Option<&'m usize> {
fake_get(map, key)
}
fn fake_get<'m, 'k1, 'k2>(_: &'m HashMap<Key<'k1>, usize>, k: &Key<'k2>) -> Option<&'m usize>
where
Key<'k1>: Borrow<Key<'k2>>,
Key<'k2>: Hash + Eq,
{
None
}
我们可以删除Hash + Eq
绑定,因为我们知道这是微不足道的。我们还可以删除HashMap
包装器:
fn get<'m, 'k1, 'k2>(map: &'m Key<'k1>, key: &Key<'k2>) -> Option<&'m usize> {
fake_get(map, key)
}
fn fake_get<'m, 'k1, 'k2>(_m: &'m Key<'k1>, _k: &Key<'k2>) -> Option<&'m usize>
where
Key<'k1>: Borrow<Key<'k2>>,
{
None
}
错误归结为Borrow
特征绑定 - 我们是否可以从另一个具有任意生命周期的Key
借用具有任意生命周期的Key
?
要做到这一点,唯一的办法是知道一辈子比另一辈子活得更久。这可以表示为:
fn get<'m, 'k1, 'k2: 'k1>(map: &'m HashMap<Key<'k1>, usize>, key: &Key<'k2>) -> Option<&'m usize>
but data from `key` is returned here
在这种情况下,我认为这不是一个很好的错误消息。我认为这可能是一个不常见的情况,尚未使用此错误消息进行润色。好消息是,您现在有一个小的复制品来提交问题:
use std::borrow::Borrow;
struct Key<'a>(&'a str);
fn get<'a, 'k1, 'k2>(k1: &'a Key<'k1>, k2: &Key<'k2>) -> &'a i32 {
fake_get(k1, k2)
}
fn fake_get<'a, 'k1, 'k2>(_k1: &'a Key<'k1>, _k2: &Key<'k2>) -> &'a i32
where
Key<'k1>: Borrow<Key<'k2>>,
{
&42
}
fn main() {}
另请参阅:
- 如何使用两个键实现哈希图?