Rust如何为自定义Point类型实现Range<T>的Iterator支持..语法
结论
目前Rust的语言设计和标准库约束下,确实无法直接使用start..end语法直接遍历两个Point构成的矩形范围,核心限制就是你提到的三个问题:
- 孤儿规则不允许为外来的
Range<T>类型实现外来的Iteratortrait Steptrait的设计不支持需要同时感知起止边界的步进逻辑,无法为Point实现该trait来让标准Range自动支持迭代- 任何尝试让
Range<Point>支持迭代的路径都绕不开Steptrait的实现要求
可行替代方案
除了你已经实现的start.to(end)写法之外,还有两个常用的可选方案:
1. 无额外自定义代码的原生迭代器组合
直接用标准库的flat_map拼接横纵坐标的范围即可,不需要为Point实现任何额外方法:
let start = Point { x: 0, y: 0 }; let end = Point { x: 3, y: 3 }; for p in (start.y..end.y).flat_map(|y| (start.x..end.x).map(move |x| Point { x, y })) { // 按行优先顺序输出所有点 println!("{:?}", p); }
2. 新类型包装绕开孤儿规则(接近原生..语法)
如果想要尽量贴近..的写法,可以定义一个新类型包装Range<Point>,为新类型实现IntoIterator:
#[derive(Clone, Debug)] struct PointRange(std::ops::Range<Point>); impl IntoIterator for PointRange { type Item = Point; type IntoIter = std::iter::FlatMap<std::ops::Range<i32>, std::iter::Map<std::ops::Range<i32>, impl FnMut(i32) -> Point>, impl FnMut(i32) -> std::iter::Map<std::ops::Range<i32>, impl FnMut(i32) -> Point>>; fn into_iter(self) -> Self::IntoIter { let (x_start, x_end) = (self.0.start.x, self.0.end.x); (self.0.start.y..self.0.end.y).flat_map(move |y| { (x_start..x_end).map(move |x| Point { x, y }) }) } } // 用法:只需要把start..end包进PointRange即可 for p in PointRange(start..end) { println!("{:?}", p); }
内容的提问来源于stack exchange,提问作者Neil Macneale
相关产品推荐
相关产品推荐

