Generics 算术运算中的泛型

Generics 算术运算中的泛型,generics,rust,Generics,Rust,我编写了一个通用函数来检查给定的数字是否为偶数: use std::ops::Rem; fn main() { let x: u16 = 31; let y: u32 = 40; println!("x = {}, y = {}", is_even(x), is_even(y)); } fn is_even<T: Rem<Output = T> + PartialEq>(n: T) -> bool { n % 2 == 0 }

我编写了一个通用函数来检查给定的数字是否为偶数:

use std::ops::Rem;

fn main() {
    let x: u16 = 31;
    let y: u32 = 40;

    println!("x = {}, y = {}", is_even(x), is_even(y));
}

fn is_even<T: Rem<Output = T> + PartialEq>(n: T) -> bool {
    n % 2 == 0
}
由于将
T
与具体的
i32
值(2和0)一起使用是一个错误,因此我编写了另一个版本的
is\u偶
如下:

fn is_even<T: Rem<Output = T> + PartialEq> (n: T, with: T, output: T) -> bool {
    n % with == output
}
fn是偶数(n:T,with:T,output:T)->bool{
n%带==输出
}
这会产生所需的输出,但是使用
is_偶数
现在是复杂的:
is_偶数(x,2,0)
。如何使我的原始版本的
工作正常


我确实认识到模运算符足够通用,可以直接处理
u16
u32
值;像
这样的函数甚至是不需要的,但我写它是为了理解泛型是如何工作的。

你对
T
的假设比你在类型中表达的要多得多。您已经正确地将
T
约束为
Rem
PartialEq
,因此可以使用
%
=
运算符,但您也假设存在属于该类型的特殊值
0
2

不存在
2
的特征,但可以使用
num traits
板条箱为具有
0
1
的类型查找特征。假设泛型类型也有addition,您可以通过向自身添加
one
来确保它也有
2

extern crate num_traits;

use num_traits::{Zero, One};
use std::ops::{Rem, Add};

fn main() {
    let x: u16 = 31;
    let y: u32 = 40;

    println!("x = {}, y = {}", is_even(x), is_even(y));
}

fn is_even<T> (n: T) -> bool 
where
    T: Rem<Output = T> + PartialEq + One + Zero + Add + Copy
{
    let one: T = One::one();
    n % (one + one) == Zero::zero()
}

我不太喜欢这个版本,因为约束
T:From
并没有真正传达函数正在做什么的有用信息。它将类型与一个深奥的实现细节联系起来,而第一个版本的约束精确地描述了需要支持的算术运算。

Peter更喜欢您的原生版本。谢谢,明白了,彼得。喜欢本机版本,因为它似乎有一个优势,当谈到模更大的数字,而不是2。第一个版本意味着
one+one+…+一个
n次。@recsubbu这个
num
板条箱有一个你可能会感兴趣的特性
fn is_even<T> (n: T) -> bool 
where
    T: Rem<Output = T> + PartialEq + From<u8>
{
    let two: T = 2u8.into();
    let zero: T = 0u8.into();
    n % two == zero
}