如何解决为什么 Vec.sort() 似乎需要静态生命周期?
这是我遇到的问题的一个大大简化的示例,但是给定一个实现 trait Thing
的 Ord
和一个实现 struct Object
的 Thing
,我具有以下结构:
pub struct MyStruct<'a> {
my_things: HashMap<i32,Vec<Box<dyn Thing + 'a>>>
}
impl<'a> MyStruct<'a> {
pub fn new() -> MyStruct<'a> {
MyStruct {
my_things: HashMap::new()
}
}
pub fn add_object(&mut self,key: i32,obj: Object) {
if !self.my_things.contains_key(&key) {
self.my_things.insert(key,Vec::new());
}
let new_thing: Box<dyn Thing> = Box::new(obj);
let things = self.my_things.get_mut(&key).unwrap();
things.push(new_thing);
things.sort();
}
}
它本质上需要一个键和一个 Object
,并使用给定的键将对象添加到 HashMap
的 Vec
中。我知道这不是执行此操作的最佳方式,但我想让它更简单以进行说明。
error[E0308]: mismatched types
--> src/main.rs:58:16
|
58 | things.sort();
| ^^^^ lifetime mismatch
|
= note: expected trait `Ord`
found trait `Ord`
note: the lifetime `'a` as defined on the impl at 42:6...
--> src/main.rs:42:6
|
42 | impl<'a> MyStruct<'a> {
| ^^
= note: ...does not necessarily outlive the static lifetime
如果我删除此示例中的所有 'a
生命周期,代码将被编译。但对于我的实际用例,我需要允许非静态生命周期。
有人能解释一下这里发生了什么吗? sort()
是否真的需要 Vec
包含具有静态生命周期的项目?如果是为什么?
有什么好的解决方法吗?
解决方法
您只为 Ord
实现了 dyn Thing + 'static
。如果您没有明确指定任何其他生命周期界限,则会推断 'static
生命周期界限。要为非 Ord
'static
实现 dyn Thing
,您需要引入和使用通用生命周期参数,例如'a
,在您的实现中。更新编译示例:
use std::collections::HashMap;
use std::cmp;
pub trait Thing {
fn priority(&self) -> i32;
}
impl<'a> PartialEq for dyn Thing + 'a { // 'a added here
fn eq(&self,other: &Self) -> bool {
self.priority() == other.priority()
}
}
impl<'a> PartialOrd for dyn Thing + 'a { // 'a added here
fn partial_cmp(&self,other: &Self) -> Option<cmp::Ordering> {
self.priority().partial_cmp(&other.priority())
}
}
impl<'a> Eq for dyn Thing + 'a {} // 'a added here
impl<'a> Ord for dyn Thing + 'a { // 'a added here
fn cmp(&self,other: &Self) -> cmp::Ordering{
self.priority().cmp(&other.priority())
}
}
pub struct Object {
priority: i32,}
impl Thing for Object {
fn priority(&self) -> i32 {
self.priority
}
}
pub struct MyStruct<'a> {
my_things: HashMap<i32,Vec<Box<dyn Thing + 'a>>>
}
impl<'a> MyStruct<'a> {
pub fn new() -> MyStruct<'a> {
MyStruct {
my_things: HashMap::new()
}
}
pub fn add_object(&mut self,key: i32,obj: Object) {
if !self.my_things.contains_key(&key) {
self.my_things.insert(key,Vec::new());
}
let new_thing: Box<dyn Thing> = Box::new(obj);
let things = self.my_things.get_mut(&key).unwrap();
things.push(new_thing);
things.sort();
}
}
fn main() {
let _test = MyStruct::new();
}
来自the Default Trait Object Lifetimes section of the Lifetime Elision chapter of the Rust Reference(强调我的):
如果 trait 对象被用作泛型类型的类型参数,那么首先使用包含类型来尝试推断边界。
- 如果包含类型有唯一的绑定,那么这是默认值
- 如果包含类型有多个边界,则必须指定显式边界
如果这些规则都不适用,则使用特征的边界:
- 如果特征是用单个生命周期绑定定义的,则使用该绑定。
- 如果 'static 用于任何生命周期绑定,则使用 'static。
- 如果 trait 没有生命周期界限,那么生命周期是在表达式中推断出来的,并且在表达式之外是
'static
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。