从您自己的迭代器返回可变引用的简单示例 [英] Simple as possible example of returning a mutable reference from your own iterator

查看:206
本文介绍了从您自己的迭代器返回可变引用的简单示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题是相关的,但它更多地涵盖了为什么编译器在从 Iterator :: next 返回可变引用时无法推断安全生命周期,我认为我理解。

This question is related, however it moreso covers the reason why the compiler cannot infer a safe lifetime when returning a mutable reference from Iterator::next, which I think I understand.

我的问题是:

在设计自己的迭代器时可以采取的具体步骤是什么可以产生可变参考?最后,我希望有一个简洁的,一步一步的评论示例: Iterator 及其 next 我(和任何人)在遇到这种情况时可以作为明确引用的实现。 不安全示例很好,我想他们可能是必要的!

What are the specific steps you can take when designing your own iterator so that it can produce mutable references? Ultimately, I'm hoping for a concise-as-possible, step-by-step, commented example of both an Iterator and its next implementation that I (and anyone) can go to as a clear reference when they run into this situation. unsafe examples are fine, I imagine they are probably necessary!

注意:我明白 MutItems 通常是推荐的示例,但由于没有任何文档,因此很难实现其实现。在那种情况下工作2.什么迭代器!宏扩展到及其工作原理。如果您使用 MutItems 作为您的示例,请说明这些事情?

NOTE: I understand that MutItems is normally the recommended example, however its implementation can be difficult to follow as there isn't any documentation on 1. How the markers work in that situation and 2. What the iterator! macro expands to and how it works. If you use MutItems as your example could you please clarify these things?

谢谢!

推荐答案

这是一种在假设的 Point 结构上有一个可变迭代器的方法。请特别注意我在 unsafe 块上添加的大量评论。我发现非常以类似的方式注释每个不安全的块非常有用,因为如果我弄错的话,我只是在脚下射击!

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);
}

这篇关于从您自己的迭代器返回可变引用的简单示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆