How do I write an iterator that returns references to itself?

前端 未结 3 1019
故里飘歌
故里飘歌 2020-11-22 14:18

I am having trouble expressing the lifetime of the return value of an Iterator implementation. How can I compile this code without changing the return value of

3条回答
  •  青春惊慌失措
    2020-11-22 14:59

    @VladimirMatveev's answer is correct in how it explains why your code cannot compile. In a nutshell, it says that an Iterator cannot yield borrowed values from within itself.

    However, it can yield borrowed values from something else. This is what is achieved with Vec and Iter: the Vec owns the values, and the the Iter is just a wrapper able to yield references within the Vec.

    Here is a design which achieves what you want. The iterator is, like with Vec and Iter, just a wrapper over other containers who actually own the values.

    use std::iter::Iterator;
    
    struct PermutationIterator<'a, T: 'a> {
        vs : Vec<&'a [T]>,
        is : Vec
    }
    
    impl<'a, T> PermutationIterator<'a, T> {
        fn new() -> PermutationIterator<'a, T> { ... }
    
        fn add(&mut self, v : &'a [T]) { ... }
    }
    
    impl<'a, T> Iterator for PermutationIterator<'a, T> {
        type Item = Vec<&'a T>;
        fn next(&mut self) -> Option> { ... }
    }
    
    fn main() {
        let v1 : Vec = (1..3).collect();
        let v2 : Vec = (3..5).collect();
        let v3 : Vec = (1..6).collect();
    
        let mut i = PermutationIterator::new();
        i.add(&v1);
        i.add(&v2);
        i.add(&v3);
    
        loop {
            match i.next() {
                Some(v) => { println!("{:?}", v); }
                None => {break;}
            }
        }
    }
    

    (Playground)


    Unrelated to your initial problem. If this were just me, I would ensure that all borrowed vectors are taken at once. The idea is to remove the repeated calls to add and to pass directly all borrowed vectors at construction:

    use std::iter::{Iterator, repeat};
    
    struct PermutationIterator<'a, T: 'a> {
        ...
    }
    
    impl<'a, T> PermutationIterator<'a, T> {
        fn new(vs: Vec<&'a [T]>) -> PermutationIterator<'a, T> {
            let n = vs.len();
            PermutationIterator {
                vs: vs,
                is: repeat(0).take(n).collect(),
            }
        }
    }
    
    impl<'a, T> Iterator for PermutationIterator<'a, T> {
        ...
    }
    
    fn main() {
        let v1 : Vec = (1..3).collect();
        let v2 : Vec = (3..5).collect();
        let v3 : Vec = (1..6).collect();
        let vall: Vec<&[i32]> = vec![&v1, &v2, &v3];
    
        let mut i = PermutationIterator::new(vall);
    }
    

    (Playground)

    (EDIT: Changed the iterator design to take a Vec<&'a [T]> rather than a Vec>. It's easier to take a ref to container than to build a container of refs.)

提交回复
热议问题