[英]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.