繁体   English   中英

为迭代器实现另一个特征

[英]Implementing another Trait for Iterator

我正在尝试向所有Iterator添加另一个特征。 但我不明白为什么它不能编译。

这是代码:

use std::fmt::Display;
use std::iter::Sum;

trait Topla<T> {
    fn topla(&mut self)-> T;
}

impl<T, I> Topla<T> for I
where
    T: Sum + Display,
    I: Iterator<Item = T>,
{
    fn topla(&mut self) -> T {
        self.sum()
    }
}

fn main() {
    let data = vec![1,2,3,5,8];
    println!("{:?}", data.iter().topla());
}

如果我们使用完全限定的 trait 语法,问题就会显现出来:

fn main() {
    let data = vec![1,2,3,5,8u32];
    let mut iter = data.iter();
    println!("{:?}", Topla::<u32>::topla(&mut iter));
}
error[E0271]: type mismatch resolving `<std::slice::Iter<'_, u32> as std::iter::Iterator>::Item == u32`
  --> src/main.rs:22:22
   |
5  |     fn topla(&mut self) -> T;
   |     ------------------------- required by `Topla::topla`
...
22 |     println!("{:?}", Topla::<u32>::topla(&mut iter));
   |                      ^^^^^^^^^^^^^^^^^^^ expected reference, found `u32`
   |
   = note: expected reference `&u32`
                   found type `u32`
   = note: required because of the requirements on the impl of `Topla<u32>` for `std::slice::Iter<'_, u32>`

Topla<u32>更改为Topla<&u32>让我们更接近:

Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `&u32: std::iter::Sum` is not satisfied
  --> src/main.rs:22:22
   |
5  |     fn topla(&mut self) -> T;
   |     ------------------------- required by `Topla::topla`
...
22 |     println!("{:?}", Topla::<&u32>::topla(&mut iter));
   |                      ^^^^^^^^^^^^^^^^^^^^ the trait `std::iter::Sum` is not implemented for `&u32`
   |
   = help: the following implementations were found:
             <u32 as std::iter::Sum<&'a u32>>
             <u32 as std::iter::Sum>
   = note: required because of the requirements on the impl of `Topla<&u32>` for `std::slice::Iter<'_, u32>`

问题是Sum<&u32>没有为&u32实现; 它是为u32实现的。 由于我们需要返回u32而不是&u32 ,因此我们需要放宽对T的要求,从作为迭代器类型本身到仅对 T 进行Sum

trait Topla<T> {
    fn topla(&mut self) -> T;
}

impl<T, I> Topla<T> for I
where
    T: Display + Sum<<I as Iterator>::Item>,
    I: Iterator,
{
    fn topla(&mut self) -> T {
        self.sum()
    }
}

fn main() {
    let data = vec![1,2,3,5,8u32];
    let mut iter = data.iter();
    println!("{:?}", Topla::<u32>::topla(&mut iter));
}

但是现在如果我们回到原来的语法,我们会遇到类型推断失败,这使得我们的新 API 使用起来非常烦人。 我们可以通过对 API 更加严格来解决这个问题。

如果我们让Topla成为Iterator的子特征,我们可以在topla方法的定义中引用项目类型,因此将 output 的类型参数移动到方法而不是特征中。 这将让我们像使用sum()一样使用 turbofish 语法。 最后我们有:

use std::fmt::Display;
use std::iter::Sum;

trait Topla: Iterator {
    fn topla<T>(self) -> T
    where
        Self: Sized,
        T: Sum<<Self as Iterator>::Item>;
}

impl<I> Topla for I
where
    I: Iterator,
    <I as Iterator>::Item: Display,
{
    fn topla<T>(self) -> T
    where
        Self: Sized,
        T: Sum<<Self as Iterator>::Item>,
    {
        self.sum()
    }
}

fn main() {
    let data = vec![1, 2, 3, 5, 8];
    println!("{:?}", data.iter().topla::<u32>());
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM