算术运算的Rust泛型[重复]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算术运算的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
}
它产生编译器错误:
error[E0308]: mismatched types
--> src/main.rs:11:9
|
11 | n % 2 == 0
| ^ expected type parameter, found integral variable
|
= note: expected type `T`
found type `{integer}`
error[E0308]: mismatched types
--> src/main.rs:11:14
|
11 | n % 2 == 0
| ^ expected type parameter, found integral variable
|
= note: expected type `T`
found type `{integer}`
由于这是使用T
与具体的i32
值(2和0)的错误,我写了另一个版本的is_even
像这样:
fn is_even<T: Rem<Output = T> + PartialEq> (n: T, with: T, output: T) -> bool {
n % with == output
}
这产生了所需的输出,但现在使用is_even
是错综复杂的:is_even(x, 2, 0)
。如何使我的原始版本的is_even
工作?
我确实认识到模运算符足够通用,可以直接使用u16
和u32
值;不需要像is_even
这样的函数 - 但是我写它是为了理解泛型如何工作。
你对T
的假设比你在类型中表达的要多得多。你已经正确地将T
约束到Rem
和PartialEq
,所以你可以使用%
和==
算子,但你也假设有特殊值0
和2
属于那种类型。
2
的存在没有特征,但你可以使用num-traits
crate来找到具有0
和1
的类型的特征。假设泛型类型也有加法,你可以通过向自身添加2
来确保它具有one
。
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: Copy
,因此它不需要在加法表达式中引用。对于大多数数字类型,这是一个合理的假设。
在不使用第三方包的情况下,您还可以使用其他类型的0
和2
的值,例如u8
,并确保您的泛型类型可以从中转换为。
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
}
我更喜欢这个版本,因为约束T: From<u8>
并没有真正传达有关函数正在做什么的任何有用信息。它将类型与深奥的实现细节联系起来,而第一个版本的约束则精确地描述了需要支持的算术运算。
以上是关于算术运算的Rust泛型[重复]的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Rust Diesel 中使用时间戳和间隔进行算术运算
获取 badarith,[erlang,'+',[error,0],[],同时使用 Erlang 片段在 TSUNG 中执行算术运算