本文介绍了有没有办法在所有引用类型上为迭代器实现一个特征?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个特点

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

我想为类型 T(在我的例子中为 f64)的所有引用类型(f64&'a f64&'a mut f64) 因为从逻辑上讲这无关紧要.

I want to implement this trait once for a type T (in my case f64) over all its reference types (f64, &'a f64, and &'a mut f64) since logically it doesn't matter.

我现在有

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
    }
}

有没有什么好的方法可以在不重复的情况下做到这一点?

Is there a good way to accomplish this without duplication?

推荐答案

您可以使用 Borrow 特性.如果您查看文档页面中的实现者,前三个在这里是相关的:这意味着 f64&'a f64&'amut f64 都实现了Borrow.您必须调用 borrow 方法对迭代器产生的每个值获取一个 &f64.

You can use the Borrow trait for this. If you look at the implementors in the documentation page, the first three are relevant here: it means that f64, &'a f64 and &'a mut f64 all implement Borrow<f64>. You'll have to call the borrow method on each value produced by the iterator to obtain a &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!()
    }
}

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


By the way, it doesn't really make sense to define a type parameter on the trait and at the same time put a constraint between that type parameter and a supertrait's associated type. A type T can only have one implementation of Iterator, therefore it can only have one implementation of Foo as well, despite the type parameter suggesting that it could implement many different Foo<T> traits. Therefore, the type parameter on Foo is completely redundant (you can just use the supertrait's associated types instead of the type parameter). Thus the code should look more like this:

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!()
    }
}

这篇关于有没有办法在所有引用类型上为迭代器实现一个特征?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-17 22:20