使用where子句实现特质:实现简单的where子句

时间:2018-12-15 18:06:15

标签: types rust traits

我一直在尝试通过rust-koans学习Rust,但是遇到了以下特征koan:

// There is an alternate syntax for placing trait bounds on a function, the
// where clause. Let's revisit a previous example, this time using 'where'.
#[test]
fn where_clause() {
    let num_one: u16 = 3;
    let num_two: u16 = 4;

    trait IsEvenOrOdd {
        fn is_even(&self) -> bool;
    }

    impl IsEvenOrOdd for u16 {
        fn is_even(&self) -> bool {
            self % 2 == 0
        }
    }

    fn asserts<T>(x: T, y: T) {
        assert!(!x.is_even());
        assert!(y.is_even());
    }

    asserts(num_one, num_two);
}

似乎目标是通过创建IsEvenOrOdd实现的通用版本来完成此代码。在这种情况下,泛型类型应具有两个边界,其余运算符和PartialEq运算符。因为右边的余数和等价的右边是整数,所以我最终编写了以下意大利面条代码:

use std::ops::Rem;

impl<T> IsEvenOrOdd for T
where
    T: Rem<u16> + Rem,
    <T as Rem<u16>>::Output: PartialEq<u16>,
{
    fn is_even(&self) -> bool {
        self % 2 == 0
    }
}

仍然-代码无法编译。看来,由于T已被取消引用,因此我需要在已取消引用的值上添加界限,但是我找不到如何执行此操作的任何示例。

error[E0369]: binary operation `%` cannot be applied to type `&T`
   --> src\koans/traits.rs:142:13
    |
142 |             self % 2 == 0
    |             ^^^^^^^^
    |
    = note: an implementation of `std::ops::Rem` might be missing for `&T`

简而言之:Rust惯用的方式来解决此问题是什么?

1 个答案:

答案 0 :(得分:1)

我认为您可能误解了此练习的意图。您想要的是什么

fn main() {
    let num_one: u16 = 3;
    let num_two: u16 = 4;

    trait IsEvenOrOdd {
        fn is_even(&self) -> bool;
    }

    impl IsEvenOrOdd for u16 {
        fn is_even(&self) -> bool {
            self % 2 == 0
        }
    }

    fn asserts<T>(x: T, y: T)
        where T: IsEvenOrOdd {
        assert!(!x.is_even());
        assert!(y.is_even());
    }

    asserts(num_one, num_two);
}

我是如何得出这个结论的?尝试编译并运行您发布的原始代码会导致以下错误:

error[E0599]: no method named `is_even` found for type `T` in the current scope
  --> src/main.rs:16:20
   |
16 |         assert!(!x.is_even());
   |                    ^^^^^^^
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `is_even`, perhaps you need to implement it:
       candidate #1: `main::IsEvenOrOdd`

此错误告诉我们要调用is_even方法,必须实现IsEvenOrOdd。您发布的示例顶部的注释说要在 function 上使用where子句。将where子句添加到函数asserts中可以解决您的问题并完成练习。