我如何判断铁锈两个特征具有相同的类型



我正在尝试为rust迭代器实现C++相邻差分算法。默认情况下,std::adjacent_different使用容器中的当前值减去其以前的值,类似于,如果我们有[5, 7, 16],那么在adjacent_difference之后,我们得到[5, 7-5, 16-7]

我试图在rust中作为迭代器扩展来做这件事,但发现Iterator::Item - Iterator::Item就是std::ops::Sub::Output,为了让Iterator::next返回类型愉快,我不得不做一些奇怪的事情,比如Some(iter_item_value - <I as Iterator>::Item::default())来获得正确的类型godbolt

struct AdjacentDifference<I>
where I: Iterator
{
prev: Option<I::Item>,
it: I,
}
impl<I> Iterator for AdjacentDifference<I>
where I: Iterator, <I as Iterator>::Item: std::ops::Sub + Default + Copy,
{
type Item = <<I as Iterator>::Item as std::ops::Sub>::Output;
fn next(&mut self) -> Option<Self::Item> {
match (self.it.next(), self.prev) {
(None, _) => None,
(Some(i), Some(p)) => {
let r = i - p;
self.prev = Some(i);
Some(r)
}
(Some(i), None) => {
self.prev = Some(i);
Some(i - <I as Iterator>::Item::default()) // <<- really?
}
}
}
}
trait AdjacentDifferenceExt: Iterator where Self: Sized,
{
fn adjacent_difference(self) -> AdjacentDifference<Self>
where <Self as Iterator>::Item: Copy,
{
AdjacentDifference {
prev: None,
it: self,
}
}
}
impl<I> AdjacentDifferenceExt for I where I: Iterator {}

它是有效的,但我不太喜欢这个代码,我是不是完全错了?有什么更好的方法可以做到这一点吗?

有多种方法可以解决此问题。

例如,一个选项只是指定减法与元素本身具有相同的类型:

impl<I> Iterator for AdjacentDifference<I>
where
I: Iterator,
I::Item: std::ops::Sub<Output = I::Item> + Copy,
{
type Item = <<I as Iterator>::Item as std::ops::Sub>::Output;
fn next(&mut self) -> Option<Self::Item> {
match (self.it.next(), self.prev) {
(None, _) => None,
(Some(i), Some(p)) => {
let r = i - p;
self.prev = Some(i);
Some(r)
}
(Some(i), None) => {
self.prev = Some(i);
Some(i)
}
}
}
}

这限制了你可以使用的类型(例如,你将无法使用Instant - Instant = Duration(,但对于大多数类型来说,这是可以的

另一个选项是指定迭代器元素类型可以通过From:转换为减法类型

impl<I> Iterator for AdjacentDifference<I>
where
I: Iterator,
I::Item: std::ops::Sub + Copy,
<I::Item as std::ops::Sub>::Output: From<I::Item>,
{
type Item = <<I as Iterator>::Item as std::ops::Sub>::Output;
fn next(&mut self) -> Option<Self::Item> {
match (self.it.next(), self.prev) {
(None, _) => None,
(Some(i), Some(p)) => {
let r = i - p;
self.prev = Some(i);
Some(r)
}
(Some(i), None) => {
self.prev = Some(i);
Some(i.into())
}
}
}
}

这将隐含地适用于减法类型是由于一揽子impl<T> From<T> for T而导致的元素类型的情况。

最新更新