Rust 链接拥有或引用的事物序列
我试图让事物具有一种特性,既可以简单地包含其他事物,也可以根据需要根据事物的名称创建它们。这些包含的东西反过来也应该能够做同样的事情,创建一个排序层次结构。下面是一个最小的代码:Rust 链接拥有或引用的事物序列,rust,lifetime,Rust,Lifetime,我试图让事物具有一种特性,既可以简单地包含其他事物,也可以根据需要根据事物的名称创建它们。这些包含的东西反过来也应该能够做同样的事情,创建一个排序层次结构。下面是一个最小的代码: use std::ops::Deref; pub enum BoxOrRef<'a, T: ?Sized + 'a> { Boxed(Box<T>), Ref(&'a T), } impl<'a, T: ?Sized + 'a> Deref for Box
use std::ops::Deref;
pub enum BoxOrRef<'a, T: ?Sized + 'a> {
Boxed(Box<T>),
Ref(&'a T),
}
impl<'a, T: ?Sized + 'a> Deref for BoxOrRef<'a, T> {
type Target = T;
fn deref(&self) -> &T {
match self {
BoxOrRef::Boxed(b) => &b,
BoxOrRef::Ref(r) => r,
}
}
}
pub trait Elem {
fn get_subelem<'a, 'b>(&'a self, name: &'b str) -> Option<BoxOrRef<'a, dyn Elem>>;
}
pub trait Table {
fn get_elem<'a, 'b>(&'a self, name: &'b str) -> Option<BoxOrRef<'a, dyn Elem>>;
}
fn resolve_name<'a, T: Table + ?Sized>(
table: &'a T,
name: &[String],
) -> Option<BoxOrRef<'a, dyn Elem>> {
let mut segments = name.iter();
if let Some(first_segment) = segments.next() {
segments.fold(table.get_elem(&first_segment), |res, next| {
res.and_then(|elem| elem.get_subelem(next))
})
} else {
None
}
}
使用std::ops::Deref;
pub enum BoxOrRef{
盒装,
参考号(&'T),
}
为BoxOrRef>执行命令;
}
pub特征表{
fn获取元素(&'a self,name:&'b str)->选项(
表:&'T,
名称:&[String],
)->选项src/lib.rs:26:17
|
26 | fn resolve_nameget_subelem
的返回值不能超过您过去调用它的&self
,因为get_subelem
的签名明确表示:
fn get_subelem<'a, 'b>(&'a self, name: &'b str) -> Option<BoxOrRef<'a, dyn Elem>>;
// ^^ ^^
一旦您将生存期参数添加到所有Elem
中,上述更改将使您的示例编译,但在实现Elem
时,这将使您处于尴尬的境地:您无法返回对self
的引用,因此实际上所有内容都必须装箱
考虑到示例的模糊性,很难给出一个好的建议,但我建议您后退一步,考虑一下
BoxOrRef
是否是这里正确的抽象。从根本上说,您不能使用BoxOrRef
做任何您不能使用引用的事情,因为BoxOrRef
可能是一个引用e、 同时,你不能用它做任何你不能用盒子
做的事情,因为它可能是一个盒子
。使用ToOwned
实现克隆
和到你拥有的
——也许类似的方法也适用于你。(如果可以的话,可以为dyn Elem
实现ToOwned
,并直接使用Cow
。)我不确定这有多大帮助,但代码可以进一步简化。我还不明白为什么这适用于&
ref,而不适用于自定义ref
包装器。@PeterHall问题在于deref
(或任何类型的访问器方法)与Ref
vs&
::不同。如果在我的示例中注释掉()
,您将得到相同的错误。如果注释掉()
和'a
,则错误消失。
pub trait Elem<'a> {
fn get_subelem(&self, name: &str) -> Option<BoxOrRef<'a, dyn Elem<'a>>>;
}