Я создал структуру данных в Rust, и я хочу создать для нее итераторы. Неизбежные итераторы достаточно просты. В настоящее время у меня это есть, и он отлично работает:Как создать собственную структуру данных с помощью итератора, который возвращает изменяемые ссылки?
// This is a mock of the "real" EdgeIndexes class as
// the one in my real program is somewhat complex, but
// of identical type
struct EdgeIndexes;
impl Iterator for EdgeIndexes {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
Some(0)
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
pub struct CGraph<E> {
nodes: usize,
edges: Vec<E>,
}
pub struct Edges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a CGraph<E>,
}
impl<'a, E> Iterator for Edges<'a, E> {
type Item = &'a E;
fn next(&mut self) -> Option<Self::Item> {
match self.index.next() {
None => None,
Some(x) => Some(&self.graph.edges[x]),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.index.size_hint()
}
}
Я хочу создать итератор, который также возвращает изменчивые ссылки. Я пытался сделать это, но не может найти способ, чтобы получить его скомпилировать:
pub struct MutEdges<'a, E: 'a> {
index: EdgeIndexes,
graph: &'a mut CGraph<E>
}
impl<'a, E> Iterator<&'a mut E> for MutEdges<'a, E> {
fn next(&mut self) -> Option<&'a mut E> {
match (self.index.next()) {
None => None,
Some(x) => Some(self.graph.edges.get_mut(x))
}
}
fn size_hint(&self) -> (uint, Option<uint>) {
self.index.size_hint()
}
}
Компиляция это приводит к следующей ошибке:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:53:24
|
53 | Some(x) => self.graph.edges.get_mut(x),
| ^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 50:45...
--> src/main.rs:50:46
|
50 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
51 | | match self.index.next() {
52 | | None => None,
53 | | Some(x) => self.graph.edges.get_mut(x),
54 | | }
55 | | }
| |_____^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:53:24
|
53 | Some(x) => self.graph.edges.get_mut(x),
| ^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the body at 50:45...
--> src/main.rs:50:46
|
50 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
51 | | match self.index.next() {
52 | | None => None,
53 | | Some(x) => self.graph.edges.get_mut(x),
54 | | }
55 | | }
| |_____^
note: ...so that types are compatible (expected std::iter::Iterator, found std::iter::Iterator)
--> src/main.rs:50:46
|
50 | fn next(&mut self) -> Option<Self::Item> {
| ______________________________________________^
51 | | match self.index.next() {
52 | | None => None,
53 | | Some(x) => self.graph.edges.get_mut(x),
54 | | }
55 | | }
| |_____^
Я не уверен, как интерпретировать эти ошибки и как изменить мой код, чтобы позволить MutEdges
возвращать изменяемые ссылки.
Ссылка на playground with code.
Я не уверен, но это может быть та же проблема, что и http://stackoverflow.com/questions/25702909/can-i-write-an-iterator-that-yields-a-reference-into -это – Levans
Не совсем, я думаю. Мой итератор не владеет объектами, к которым он возвращает изменчивые ссылки, которые он делает. Я думаю, что это возможно, учитывая, что стандартная библиотека Rust [уже имеет итераторы изменчивых ссылок] (http://doc.rust-lang.org/std/slice/struct.MutItems.html) –
В их реализации используется устаревшая функция ' mut_shift_ref() ', возможно, вы можете найти то, что вам нужно: http://doc.rust-lang.org/std/slice/trait.MutableSlice.html#tymethod.mut_shift_ref – Levans