我有一个自定义特性,我想要在一个 HashMap<(u32, u32), &'a Edge>
上实现它。由于我希望我的特性能够在所拥有的值和引用值上工作,因此我使用了其他 SO 帖子建议的 Borrow
特性,但是我在处理借用检查器和引用的 &Edge
时遇到了问题。首先,编译器要求我为 &Edge
明确添加生命周期,就像您下面看到的那样。
然而,然后编译器会抱怨函数 get_edge
的返回类型(Option<&'a Edge>
)与特性定义的返回类型(Option<&Edge>
)不匹配。在我看来,为我的特性定义添加生命周期参数是没有意义的,因此我猜错误一定出现在我对特性的实现上。然而,无论我尝试哪些生命周期参数组合,都没能让编译器满意。我在这里到底做错了什么?
pub struct Edge {
between: (u32, u32),
weight: u32,
}
impl Edge {
pub fn normalize_edge(v1: u32, v2: u32) -> (u32, u32) {
(v1.min(v2), v1.max(v2))
}
fn get_weight(&self) -> u32 {
self.weight
}
}
trait EdgeFinder {
fn get_edge(&self, v1: u32, v2: u32) -> Option<&Edge>;
fn get_weight(&self, v1: u32, v2: u32) -> Option<u32>;
}
impl<'a, 'b, B: Borrow<HashMap<(u32, u32), &'a Edge>> + 'b> EdgeFinder for B {
fn get_edge(&self, v1: u32, v2: u32) -> Option<&Edge> {
self.borrow().get(&Edge::normalize_edge(v1, v2)).map(|&e| e)
}
fn get_weight(&self, v1: u32, v2: u32) -> Option<u32> {
self.get_edge(v1, v2).and_then(|v| Some(v.get_weight()))
}
}
编辑:
虽然它可能不重要,但我已经添加了Edge
的定义。这是编译器的输出:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/graph.rs:44:23
|
44 | self.borrow().get(&(0,0)).map(|&e| e)
| ^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 41:6...
--> src/graph.rs:41:6
|
41 | impl<'a, 'b, B: 'b + Borrow<HashMap<(u32, u32), &'a Edge>>> EdgeFinder for B {
| ^^
note: ...so that the types are compatible
--> src/graph.rs:44:23
|
44 | self.borrow().get(&(0,0)).map(|&e| e)
| ^^^
= note: expected `&HashMap<(u32, u32), &Edge>`
found `&HashMap<(u32, u32), &'a Edge>`
note: but, the lifetime must be valid for the anonymous lifetime defined on the method body at 42:17...
--> src/graph.rs:42:17
|
42 | fn get_edge(&self, v1: u32, v2: u32) -> Option<&Edge> {
| ^^^^^
note: ...so that the expression is assignable
--> src/graph.rs:44:9
|
44 | self.borrow().get(&(0,0)).map(|&e| e)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `Option<&Edge>`
found `Option<&Edge>`
编辑2:
为了补充一点上下文,我尝试在EdgeFinder
周围创建一个包装结构,但我不想强制规定被包装的 EdgeFinder
是拥有者还是引用。
pub struct EdgeViewer<T: EdgeFinder> {
inner: T,
}
impl<T: EdgeFinder> EdgeViewer<T> {
//Obviously works for owned values.
pub fn new(inner: T) -> Self {
EdgeViewer { inner }
}
}
然而,当使用引用时,会出现以下编译器输出,这使我相信我需要为引用的版本特别添加一个实现。
error[E0277]: the trait bound `&HashMap<(u32, u32), &Edge>: EdgeFinder` is not satisfied
--> src/construction.rs:74:43
|
74 | let mut edge_viewer = EdgeViewer::new(&edges);
| -^^^^^
| |
| the trait `EdgeFinder` is not implemented for `&HashMap<(u32, u32), &Edge>`
| help: consider removing the leading `&`-reference
|
= help: the following implementations were found:
<HashMap<(u32, u32), &Edge> as EdgeFinder>
note: required by `EdgeViewer::<T>::new`
--> src/graph.rs:58:5
|
58 | pub fn new(inner: T) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Borrow
,但我并不确定这是否是正确的方法。playground。如果您同意,我可以从中得出答案吗? - Jerboas86