簡體   English   中英

實現特征時如何在類型上施加特征約束?

[英]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您正在移動 valuenext移出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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM