![](/img/trans.png)
[英]How may I return an iterator over the keys of a HashMap that clones the keys?
[英]How to return an iterator over the keys of a HashMap from a trait implementation?
我正在尝试在 Rust 中构建一个简单的图形库。 任何图都必须实现一个特征Graph
。 这个特征目前只有一个 function nodes
,它允许使用 for-in 循环迭代图的节点。
Graph
的一个实现MapGraph
是围绕HashMap
的轻量级包装器。 MapGraph
必须实现Graph
trait 方法nodes
。 我在让它工作时遇到问题。
这是Graph
的代码:
pub trait Graph<N> {
fn nodes(&self) -> Box<dyn Iterator<Item = &N>>;
}
这是MapGraph
的代码:
use std::collections::HashMap;
use crate::rep::Graph;
pub struct MapGraph<N> {
map: HashMap<N, HashMap<N, ()>>
}
impl<N> MapGraph<N> {
pub fn new(map: HashMap<N, HashMap<N, ()>>) -> Self {
MapGraph { map }
}
}
impl<N> Graph<N> for MapGraph<N> {
fn nodes(&self) -> Box<dyn Iterator<Item=&N>> {
let keys = self.map.keys();
Box::new(keys)
}
}
编译器给出了这个错误:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:19:29
|
19 | let keys = self.map.keys();
| ^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 18:5...
--> src/lib.rs:18:5
|
18 | / fn nodes(&self) -> Box<dyn Iterator<Item = &N>> {
19 | | let keys = self.map.keys();
20 | |
21 | | Box::new(keys)
22 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:19:20
|
19 | let keys = self.map.keys();
| ^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
= note: ...so that the expression is assignable:
expected std::boxed::Box<(dyn std::iter::Iterator<Item = &N> + 'static)>
found std::boxed::Box<dyn std::iter::Iterator<Item = &N>>
我找到了有关此错误的其他参考,但这些情况似乎不像我这里的情况。
我使用Box
是因为Graph
特征有一个 function 本身返回一个特征。 返回迭代器(或任何其他特征)的正确方法是什么? 将这种方法作为一种选择,而我无法实现其他任何一种方法。 如果有其他方法可以做到这一点,那很好。
我有哪些解决这个特定问题的选择?
如果您明确指定要返回的特征 object ( dyn Iterator
) 包含与self
的生命周期相关的引用,则它可以工作。
如果不添加此绑定,编译器无法从 function 签名中推断出在self
移动或销毁后无法使用迭代器。 因为编译器无法推断这一点,所以它不能安全地在函数的 output 中使用self.map.keys()
。
添加了此绑定的工作示例:
pub trait Graph<N> {
fn nodes<'a>(&'a self) -> Box<dyn Iterator<Item = &N> + 'a>;
}
use std::collections::HashMap;
pub struct MapGraph<N> {
map: HashMap<N, HashMap<N, ()>>,
}
impl<N> MapGraph<N> {
pub fn new(map: HashMap<N, HashMap<N, ()>>) -> Self {
MapGraph { map }
}
}
impl<N> Graph<N> for MapGraph<N> {
fn nodes<'a>(&'a self) -> Box<dyn Iterator<Item = &N> + 'a> {
let keys = self.map.keys();
Box::new(keys)
}
}
我曾认为Item = &'a N
的界限也是必需的,但我想这已经被“ + 'a
”覆盖了......
请注意,要理解以下错误:
expected std::boxed::Box<(dyn std::iter::Iterator<Item = &N> + 'static)>
found std::boxed::Box<dyn std::iter::Iterator<Item = &N>>
您必须了解,出于人体工程学原因,编译器会自动将+ 'static
生命周期限定符添加到任何不合格的特征 object。 这意味着编译器将不合格的Box<dyn MyTrait>
转换为Box<(dyn MyTrait + 'static)>
,这反过来意味着 object 不能包含任何引用,除了那些持续整个程序的生命周期的引用. 考虑到这一点,您可以看到为什么self.map.keys()
不符合这个严格的界限,需要更具体的明确界限。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.