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的强转,有没有相关资料可以参考呢?
1
共 6 条评论, 1 页
评论区
写评论是的,我以为语法上只能把T写左边; 看起来只要约束关系成立,不论T在哪边都可以
--
👇
7sDream: 我记得以前 TRPL 里是写了 Where 子句的 T 可以出现在右边来着,刚翻了一下现在这版本好像确实没提这一点了……
其实就是 Trait Bound 并不是直接对 T 做限制,而是陈述了一个约束,只要 T 可以让这个约束成立,T 就是满足约束的。所以 T 出现在右边也行。
Rust Reference 里还是稍微写了几个例子的。
谢谢指教,学习到了
👇
苦瓜小仔:
最后,省略 Sized,运用
+
进行 trait bounds 合并,你的代码可以得到更简洁的形式:从简单的角度出发:where 语句的内容几乎是你可以用任何 trait boudns 表达的内容,所以
u8: TryInto<T>
的形式并不奇怪, 甚至出现u8: Eq
这种永远成立且不含类型参数的泛型也是合法的(这种情况是我给的第二个 RFC 链接所实现的,虽然正常情况下几乎不会手写,但却是宏在某些情况下的技巧)。这涉及 where 语句的设计,想弄清楚就去看 RFC:
https://rust-lang.github.io/rfcs/0135-where.html
https://rust-lang.github.io/rfcs/2056-allow-trivial-where-clause-constraints.html
此外,下面的代码与你的代码等价,这可能是你觉得熟悉的形式:
我记得以前 TRPL 里是写了 Where 子句的 T 可以出现在右边来着,刚翻了一下现在这版本好像确实没提这一点了……
其实就是 Trait Bound 并不是直接对 T 做限制,而是陈述了一个约束,只要 T 可以让这个约束成立,T 就是满足约束的。所以 T 出现在右边也行。
Rust Reference 里还是稍微写了几个例子的。