首页 > 解决方案 > 迭代结构中的内部字段

问题描述

我想在一个内部字段上实现Iterator一个struct如此轻松的循环,但我无法让它工作。

从返回IterWrapper::next()是错误的。

也许有一个更简单的解决方案来实现这一点。

struct Wrapper {
    pub items: Vec<String>
}

struct IterWrapper<'a> {
    inner: &'a std::slice::Iter<'a, String>,
}

impl<'a> Iterator for IterWrapper<'a> {
    type Item = &'a String;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner.next();
    }
}

impl Wrapper {
    fn iter<'a>(&'a self) -> IterWrapper<'a> {
        IterWrapper {
            inner: &self.items.iter(),
        }
    }
}

fn main() {
    
    let w = Wrapper {
        items: vec![String::from("test1"), String::from("test2")]
    };

    for item in w.iter() {
        println!("{}", item);
    }

}
error[E0308]: mismatched types
  --> src/main.rs:13:27
   |
13 |     fn next(&mut self) -> Option<Self::Item> {
   |        ----               ^^^^^^^^^^^^^^^^^^ expected enum `std::option::Option`, found `()`
   |        |
   |        implicitly returns `()` as its body has no tail or `return` expression
14 |         self.inner.next();
   |                          - help: consider removing this semicolon
   |
   = note:   expected enum `std::option::Option<&std::string::String>`
           found unit type `()`

标签: rust

解决方案


您必须进行一些更改:

struct Wrapper {
    pub items: Vec<String>
}

struct IterWrapper<'a> {
    // this needs to own the iterator, not a reference to it
    // in order to avoid returning a borrowed value
    inner: std::slice::Iter<'a, String>,
}

impl<'a> Iterator for IterWrapper<'a> {
    type Item = &'a String;

    fn next(&mut self) -> Option<Self::Item> {
        // no semicolon here so the result is implicitly returned
        // your old error happened because the semicolon causes the value to not be returned
        self.inner.next()
    }
}

impl Wrapper {
    fn iter<'a>(&'a self) -> IterWrapper<'a> {
        IterWrapper {
            // give the iterator, not the reference to it
            inner: self.items.iter(),
        }
    }
}

fn main() {
    
    let w = Wrapper {
        items: vec![String::from("test1"), String::from("test2")]
    };

    for item in w.iter() {
        println!("{}", item);
    }

}

推荐阅读