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