[英]How can I put a trait constraint on a type while implementing a trait?
我有一個生成斐波那契數的迭代器。 我將類型限制為u32
,但是現在我正在努力使其對任何數字類型通用。
有效的非通用代碼:
struct Fib {
value: u32,
next: u32,
}
impl Fib {
fn new( a : u32, b : u32 ) -> Fib {
Fib { value : a, next : b }
}
}
impl Iterator for Fib {
type Item = u32;
fn next(&mut self) -> Option<u32> {
let value = self.value;
let next = self.value + self.next;
self.value = self.next;
self.next = next;
Some( value )
}
}
//////////////////////////////////////////////////
fn main() {
let fib = Fib::new( 1, 2 );
let sum = fib.filter( |x| { x % 2 == 0 })
.take_while( |&x| { x <= 4000000 })
.fold( 0, |sum, x| { sum + x });
println!("{}", sum);
}
問題是Iterator
的實現需要對Num
進行約束,但是我不知道如何表達這一點:
impl <T : Num> Iterator for Fib<T> { ... }
生產:
use of undeclared trait name `Num`
當我嘗試use std::num::{Num}
或use num::traits::{Num}
,會被告知模塊不存在。
我不認為您希望Fib
在數字類型上通用,但要實現+
運算符的類型。 像這樣:
use std::ops::Add;
struct Fib<N>
where N: Add<Output = N> + Copy {
value: N,
next: N,
}
impl<N> Iterator for Fib<N>
where N: Add<Output = N> + Copy {
type Item = N;
fn next(&mut self) -> Option<N> {
let next = self.value + self.next;
self.value = self.next;
self.next = next;
Some(next)
}
}
fn main() {
let fib_seq = Fib {
value: -1,
next: 1,
};
for thing in fib_seq.take(10) {
println!("{}", thing);
}
}
Add
是允許您使用+
運算符並產生Output
。 在這種情況下, N
實現Add<Output = N>
特性,這意味着N + N
將產生類型N
東西。
聽起來像這樣,但是當您嘗試執行self.next + self.value
您正在移動 value
, next
移出self
,導致錯誤。
您不能不移動值,因為add的定義具有以下方法簽名:
fn add(self, rhs: RHS) -> Self::Output;
在Add
的案例中, RHS
只是Self
。 因此,為了將N
限制為僅需很少開銷即可復制的類型,我添加了Copy
trait作為限制。
OP提到了一個有趣的觀點:是否可以別名特征? 簡而言之,沒有。 您可以創建一個新特征:
trait SimpleAdd: Add<Output = Self> + Copy {
}
但是,那么您將必須針對所需的所有類型實現該特征。 即, i32
不會自動實現SimpleAdd
。 但是,如果需要,可以使用泛型來實現:
impl<N> SimpleAdd for N
where N: Add<Output = N> + Copy {
}
因此,以上兩個塊將為您提供與特質別名相同的功能,但似乎很麻煩。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.