有没有办法一般地为所有引用类型实现迭代器的特征?

mic*_*612 10 rust

我有一个特点

trait Foo<T> : Iterator<Item=T> {
    fn bar(&mut self) -> f64;
}
Run Code Online (Sandbox Code Playgroud)

我想一旦实现这种特质的类型T(在我的情况下f64在其所有引用类型() f64,&'a f64&'a mut f64),因为在逻辑上也没关系.

我现在有

impl<T: Iterator<Item = f64>> Foo<f64> for T {
    fn bar(&mut self) -> f64 {
        // duplicated code
    }
}

impl<'a, T: Iterator<Item = &'a f64>> Foo<&'a f64> for T {
    fn bar(&mut self) -> f64 {
        // duplicated code
    }
}

impl<'a, T: Iterator<Item = &'a mut f64>> Foo<&'a mut f64> for T {
    fn bar(&mut self) -> f64 {
        // duplicated code
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有一个很好的方法来完成这个没有重复?

Fra*_*gné 7

你可以使用这个Borrow特性.如果您查看文档页面中的实现者,前三个是相关的:它意味着f64,&'a f64并且&'a mut f64所有实现Borrow<f64>.您必须borrow在迭代器生成的每个值上调用该方法来获取&f64.

use std::borrow::Borrow;

impl<T> Foo<T::Item> for T
    where T: Iterator,
          T::Item: Borrow<f64>
{
    fn bar(&mut self) -> f64 {
        unimplemented!()
    }
}
Run Code Online (Sandbox Code Playgroud)

顺便说一下,在特征上定义一个类型参数并同时在该类型参数和一个supertrait的相关类型之间设置一个约束是没有意义的.一个类型T只能有一个实现Iterator,因此它只能有一个实现Foo,尽管类型参数表明它可以实现许多不同的Foo<T>特性.因此,类型参数on Foo是完全冗余的(您可以只使用supertrait的关联类型而不是type参数).因此代码看起来应该更像这样:

use std::borrow::Borrow;

trait Foo: Iterator {
    fn bar(&mut self) -> f64;
}

impl<T> Foo for T
    where T: Iterator,
          T::Item: Borrow<f64>
{
    fn bar(&mut self) -> f64 {
        unimplemented!()
    }
}
Run Code Online (Sandbox Code Playgroud)