我如何创建一个 trait/type 来统一迭代来自 Range 或 Vec 的一些整数集?
How can I create a trait/type to unify iterating over some set of integers from either a Range or a Vec?
我需要特征 XYZ
来定义一个允许迭代某些整数集的方法。这组整数由支持 Vec
或 Range<usize>
定义。但是,我 运行 陷入各种(生命周期或类型)问题,具体取决于我如何定义 XYZIterator
类型,该类型应该将这些 Iterator
统一到 Vec
/Range
.
备份方案是分配和return Vec
s,但我想知道是否有没有cloning/allocating内存的方法。
type XYZIterator = Box<dyn Iterator<Item = usize>>;
trait XYZ {
fn stuff(&self) -> XYZIterator;
}
struct Test {
objects: Vec<usize>,
}
impl XYZ for Test {
fn stuff(&self) -> XYZIterator {
Box::new(self.objects.iter())
}
}
struct Test2 {}
impl XYZ for Test2 {
fn stuff(&self) -> XYZIterator {
Box::new((1..4).into_iter())
}
}
fn main() {
let t1 = Test {
objects: vec![1, 2, 3],
};
let t2 = Test2 {};
t1.stuff().for_each(|x| println!("{}", x));
t2.stuff().for_each(|x| println!("{}", x));
t1.stuff()
.filter(|x| x % 2 == 0)
.for_each(|x| println!("{}", x));
t2.stuff()
.filter(|x| x % 2 == 0)
.for_each(|x| println!("{}", x));
}
error[E0271]: type mismatch resolving `<std::slice::Iter<'_, usize> as Iterator>::Item == usize`
--> src/main.rs:12:9
|
12 | Box::new(self.objects.iter())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference
|
= note: expected type `usize`
found reference `&usize`
= note: required for the cast to the object type `dyn Iterator<Item = usize>`
您的代码有两个问题:
在为 Test1
实现 XYZ
时,您 return 迭代器 self.objects.iter()
。 Vec::iter
遍历 references 到对象,而不是对象本身,所以这是一个遍历 &usize
的迭代器,它与 return 类型不匹配.你应该得到一个关于这个的错误。虽然很容易修复:self.objects.iter().copied()
将从引用中复制每个元素。
在type XYZIterator = Box<dyn Iterator<Item = usize>>;
中,由于trait对象中没有生命周期,所以默认为'static——也就是说,你的迭代器可以永远存在。但是向量迭代器不是这种情况——它有一个对正在迭代的向量的引用。这是您遇到终身问题的地方。
解决方案是给 XYZIterator
类型一个生命周期:
type XYZIterator<'a> = Box<dyn Iterator<Item = usize> + 'a>;
并更改特征和特征实现以使用生命周期。
还可以考虑更改您的类型或函数以接受任何 T: Iterator<Item=usize>
;然后它将接受任何产生 usize
s
的迭代器
我需要特征 XYZ
来定义一个允许迭代某些整数集的方法。这组整数由支持 Vec
或 Range<usize>
定义。但是,我 运行 陷入各种(生命周期或类型)问题,具体取决于我如何定义 XYZIterator
类型,该类型应该将这些 Iterator
统一到 Vec
/Range
.
备份方案是分配和return Vec
s,但我想知道是否有没有cloning/allocating内存的方法。
type XYZIterator = Box<dyn Iterator<Item = usize>>;
trait XYZ {
fn stuff(&self) -> XYZIterator;
}
struct Test {
objects: Vec<usize>,
}
impl XYZ for Test {
fn stuff(&self) -> XYZIterator {
Box::new(self.objects.iter())
}
}
struct Test2 {}
impl XYZ for Test2 {
fn stuff(&self) -> XYZIterator {
Box::new((1..4).into_iter())
}
}
fn main() {
let t1 = Test {
objects: vec![1, 2, 3],
};
let t2 = Test2 {};
t1.stuff().for_each(|x| println!("{}", x));
t2.stuff().for_each(|x| println!("{}", x));
t1.stuff()
.filter(|x| x % 2 == 0)
.for_each(|x| println!("{}", x));
t2.stuff()
.filter(|x| x % 2 == 0)
.for_each(|x| println!("{}", x));
}
error[E0271]: type mismatch resolving `<std::slice::Iter<'_, usize> as Iterator>::Item == usize`
--> src/main.rs:12:9
|
12 | Box::new(self.objects.iter())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found reference
|
= note: expected type `usize`
found reference `&usize`
= note: required for the cast to the object type `dyn Iterator<Item = usize>`
您的代码有两个问题:
在为
Test1
实现XYZ
时,您 return 迭代器self.objects.iter()
。Vec::iter
遍历 references 到对象,而不是对象本身,所以这是一个遍历&usize
的迭代器,它与 return 类型不匹配.你应该得到一个关于这个的错误。虽然很容易修复:self.objects.iter().copied()
将从引用中复制每个元素。在
type XYZIterator = Box<dyn Iterator<Item = usize>>;
中,由于trait对象中没有生命周期,所以默认为'static——也就是说,你的迭代器可以永远存在。但是向量迭代器不是这种情况——它有一个对正在迭代的向量的引用。这是您遇到终身问题的地方。解决方案是给
XYZIterator
类型一个生命周期:type XYZIterator<'a> = Box<dyn Iterator<Item = usize> + 'a>;
并更改特征和特征实现以使用生命周期。
还可以考虑更改您的类型或函数以接受任何 T: Iterator<Item=usize>
;然后它将接受任何产生 usize
s