< 返回版块

wangshankun 发表于 2022-07-21 19:51

use std::fmt::Debug;
use std::convert::TryInto;
use std::ops::Rem;

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

// generic blanket impl
impl<T> Even for T
where
    T: Rem<Output = T> + PartialEq<T> + Sized,
    u8: TryInto<T>,
    <u8 as TryInto<T>>::Error: Debug,
{
    fn is_even(self) -> bool {
        // these unwraps will never panic
        self % 2.try_into().unwrap() == 0.try_into().unwrap()
    }
}

#[test] // 
fn test_is_even() {
    assert!(2_i8.is_even());
    assert!(4_u8.is_even());
    assert!(6_i16.is_even());
    // etc
}

约束条件里面,这两项是什么意思呢?是对T的约束吗?看文法像是对u8类型的约束?

u8: TryInto<T>,

<u8 as TryInto<T>>::Error: Debug,

结合上下文猜测表达的是T需要实现u8的强转,有没有相关资料可以参考呢?

评论区

写评论
作者 wangshankun 2022-07-21 21:01

是的,我以为语法上只能把T写左边; 看起来只要约束关系成立,不论T在哪边都可以

--
👇
7sDream: 我记得以前 TRPL 里是写了 Where 子句的 T 可以出现在右边来着,刚翻了一下现在这版本好像确实没提这一点了……

其实就是 Trait Bound 并不是直接对 T 做限制,而是陈述了一个约束,只要 T 可以让这个约束成立,T 就是满足约束的。所以 T 出现在右边也行。

Rust Reference 里还是稍微写了几个例子的。

作者 wangshankun 2022-07-21 20:59

谢谢指教,学习到了

👇
苦瓜小仔:

苦瓜小仔 2022-07-21 20:39

最后,省略 Sized,运用 + 进行 trait bounds 合并,你的代码可以得到更简洁的形式:

impl<T> Even for T
where
    T: Rem<Output = T> + PartialEq<T> + TryFrom<u8>,
    <T as TryFrom<u8>>::Error: Debug,
苦瓜小仔 2022-07-21 20:27

从简单的角度出发:where 语句的内容几乎是你可以用任何 trait boudns 表达的内容,所以 u8: TryInto<T> 的形式并不奇怪, 甚至出现 u8: Eq 这种永远成立且不含类型参数的泛型也是合法的(这种情况是我给的第二个 RFC 链接所实现的,虽然正常情况下几乎不会手写,但却是宏在某些情况下的技巧)。

苦瓜小仔 2022-07-21 20:19

这涉及 where 语句的设计,想弄清楚就去看 RFC:

https://rust-lang.github.io/rfcs/0135-where.html

https://rust-lang.github.io/rfcs/2056-allow-trivial-where-clause-constraints.html

此外,下面的代码与你的代码等价,这可能是你觉得熟悉的形式:

impl<T> Even for T
where
    T: Rem<Output = T> + PartialEq<T> + Sized,
    T: TryFrom<u8>,
    <T as TryFrom<u8>>::Error: Debug,
{
    fn is_even(self) -> bool {
        self % 2.try_into().unwrap() == 0.try_into().unwrap()
    }
}
7sDream 2022-07-21 20:14

我记得以前 TRPL 里是写了 Where 子句的 T 可以出现在右边来着,刚翻了一下现在这版本好像确实没提这一点了……

其实就是 Trait Bound 并不是直接对 T 做限制,而是陈述了一个约束,只要 T 可以让这个约束成立,T 就是满足约束的。所以 T 出现在右边也行。

Rust Reference 里还是稍微写了几个例子的。

1 共 6 条评论, 1 页