gpt4 book ai didi

rust - 将自由函数迁移到特征时的生命周期不匹配

转载 作者:行者123 更新时间:2023-11-29 08:29:37 27 4
gpt4 key购买 nike

我实现了这个小函数,它返回对枚举值的引用。这很好用:

pub enum Entry {
COMMENT,
NUM(Option<String>, f64),
STR(Option<String>, String),
VNUM(Option<String>, Vec<f64>),
VSTR(Option<String>, Vec<String>),
}

pub fn get_value<'b>(k: &str, entity: &'b [Entry]) -> Option<&'b str> {
entity
.iter()
.filter_map(|x| match x {
&Entry::STR(ref key, ref v) => if key.as_ref().unwrap().as_str() == k {
Some(v.as_str())
} else {
None
},
_ => None,
})
.next()
}
fn main() {
let v = vec![
Entry::STR(Some("foo".to_string()), "bar".to_string()),
Entry::NUM(Some("baz".to_string()), 1234f64),
];
let x: Option<&str> = get_value("foo", &v);
}

为了注入(inject)一些多态性,我想将其移动到一个特征中,以便我可以为不同的类型调用它

pub trait GetValue<T> {
fn get_value<'a>(k: &str, entity: &'a [Entry]) -> Option<&'a str>;
}

impl<'a> GetValue<&'a str> for &'a [Entry] {
fn get_value(k: &str, entity: &'a [Entry]) -> Option<&'a str> {
entity
.iter()
.filter_map(|x| match x {
&Entry::STR(ref key, ref v) => if key.as_ref().unwrap().as_str() == k {
Some(v.as_str())
} else {
None
},
_ => None,
})
.next()
}
}

但尽管没有故意更改生命周期规范,但仍会出现以下错误。我错过了什么?

error[E0308]: method not compatible with trait
--> src/main.rs:14:5
|
14 | fn get_value(k: &str, entity: &'a [Entry]) -> Option<&'a str> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `fn(&str, &'a [Entry]) -> std::option::Option<&'a str>`
found type `fn(&str, &'a [Entry]) -> std::option::Option<&'a str>`
note: the lifetime 'a as defined on the method body at 14:5...
--> src/main.rs:14:5
|
14 | fn get_value(k: &str, entity: &'a [Entry]) -> Option<&'a str> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 13:1
--> src/main.rs:13:1
|
13 | impl<'a> GetValue<&'a str> for &'a [Entry] {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: method not compatible with trait
--> src/main.rs:14:5
|
14 | fn get_value(k: &str, entity: &'a [Entry]) -> Option<&'a str> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `fn(&str, &'a [Entry]) -> std::option::Option<&'a str>`
found type `fn(&str, &'a [Entry]) -> std::option::Option<&'a str>`
note: the lifetime 'a as defined on the impl at 13:1...
--> src/main.rs:13:1
|
13 | impl<'a> GetValue<&'a str> for &'a [Entry] {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime 'a as defined on the method body at 14:5
--> src/main.rs:14:5
|
14 | fn get_value(k: &str, entity: &'a [Entry]) -> Option<&'a str> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

最佳答案

通过将 &'a [Entry]&'a str 分别替换为 SelfT您的 get_value 方法的签名,您摆脱了特征定义中的显式生命周期。因此,GetValue 的定义变得独立于 &'a [Entry]&'a str 类型,它们特定于&'a [Entry] 的具体实现。作为副作用,您一生的问题将会消失。

pub trait GetValue<T> {
fn get_value(self, k: &str) -> Option<T>;
}

impl<'a> GetValue<&'a str> for &'a [Entry] {
fn get_value(self, k: &str) -> Option<&'a str> {
self.iter()
.filter_map(|x| match x {
&Entry::STR(ref key, ref v) =>
if key.as_ref().unwrap().as_str() == k {
Some(v.as_str())
} else {
None
},
_ => None,
})
.next()
}
}

这样,get_value 消耗self。在您对 &'a [Entry] 的实现中,方法 get_value 使用类型为 &'a [Entry] 的内容。不可变引用是 Copy,所以在这个实现中 get_value 实际上只消耗一个副本(&'a [Entry] 类型的东西在之后仍然可用在其上调用了 get_value)。

GetValue 也可以为不是Copy 的东西实现。在此类类型的实例上调用 get_value 将消耗此实例。如果你想让get_value在这方面有更多的限制,你可以让它以&'a self作为参数而不是self。这需要一个明确的生命周期 'a 你的特征:

pub trait GetValue<'a, T> {
fn get_value(&'a self, k: &str) -> Option<T>;
}

impl<'a> GetValue<'a, &'a str> for [Entry] {
fn get_value(&'a self, k: &str) -> Option<&'a str> { ... }
}

关于rust - 将自由函数迁移到特征时的生命周期不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49821121/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com