从您自己的迭代器返回可变引用的简单示例 [英] Simple as possible example of returning a mutable reference from your own iterator
问题描述
这个问题是相关的,但它更多地涵盖了为什么编译器在从 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屋!