Simple as possible example of returning a mutable reference from your own iterator

十年热恋 提交于 2019-12-01 21:56:20

Here's a way of having a mutable iterator over a hypothetical Point struct. Pay special attention to the large comment that I put on the unsafe block. I find it very useful to annotate every unsafe block in a similar fashion, since I'm only shooting myself in the foot if I get it wrong!

use std::mem;

#[derive(Debug)]
struct Point {
    x: u8,
    y: u8,
    z: u8,
}

impl Point {
    fn iter_mut(&mut self) -> IterMut {
        IterMut { point: self, idx: 0 }
    }
}

struct IterMut<'a> {
    point: &'a mut Point,
    idx: u8,
}

impl<'a> Iterator for IterMut<'a> {
    type Item = &'a mut u8;

    fn next(&mut self) -> Option<&'a mut u8> {
        let retval = match self.idx {
            0 => Some(&mut self.point.x),
            1 => Some(&mut self.point.y),
            2 => Some(&mut self.point.z),
            _ => None
        };

        if retval.is_some() {
            self.idx += 1;
        }

        // This is safe because...
        // (from http://stackoverflow.com/questions/25730586):
        // The Rust compiler does not know that when you ask a mutable
        // iterator for the next element, that you get a different
        // reference every time and never the same reference twice. Of
        // course, we know that such an iterator won't give you the
        // same reference twice.
        unsafe { mem::transmute(retval) }
    }
}

fn main() {
    let mut p1 = Point { x: 1, y: 2, z: 3 };

    for x in p1.iter_mut() {
        *x += 1;
    }

    println!("{:?}", p1);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!