繁体   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