我正在学习Rust中的泛型。我创建了一个简单的用例,使用一个函数来计算其面积。请考虑下面的例子:
#[derive(Debug)]
struct Trapezium<T> {
a: T,
b: T,
h: T,
area: T,
perimeter: T,
}
fn calc_area<T: std::ops::Add>(a: T, b: T, h: T) -> T {
return (a+b)/2.0/h;
}
fn main() {
let mut t = Trapezium {a: 3.1, b: 6.9, h: 2.5, area: 0.0, perimeter: 0.0};
t.area = calc_area(t.a, t.b, t.h);
println!("t: {:?}", t);
}
字符串
我在calc_area
函数中遇到了一个问题,因为被float64
整除。请在下面找到我的编译错误:
Compiling geometric v0.1.0 (/Users/mabalenk/repo/git/rustup/src/geometric)
error[E0369]: cannot divide `<T as Add>::Output` by `{float}`
--> src/main.rs:12:17
|
12 | return (a+b)/2.0/h;
| -----^--- {float}
| |
| <T as Add>::Output
|
help: consider further restricting the associated type
|
10 | fn calc_area<T: std::ops::Add>(a: T, b: T, h: T) -> T where <T as Add>::Output: Div<f64> {
| ++++++++++++++++++++++++++++++++++
For more information about this error, try `rustc --explain E0369`.
error: could not compile `geometric` (bin "geometric") due to previous error
型
我对添加where <T as Add>::Output: Div<f64>
子句的建议感到担忧。Div<f64>
不再使其通用。加上添加此子句对编译代码没有帮助。而且它确实使源代码非常混乱。
你能建议一个优雅的'教科书'解决方案,使我的基本例子工作?
2条答案
按热度按时间fykwrbwg1#
T: std::ops::Add
确保你可以计算a+b
,但它不允许你计算/2.0/h
。你至少需要T: std::ops::Div
,这样你才能计算/h
,再加上一些方法来允许/2.0
。编译器试图建议一种允许除以2的方法,但还有其他方法。最简单的方法之一是确保您可以从
2.0
(可以表示为T: From<f32>
)构造T
,因为您已经需要T: std::ops::Div
。此外,由于您的函数返回
T
类型的值,您还需要告诉编译器所有这些操作都返回T
s。完整示例:
字符串
Playground
cig3rfwq2#
通过使用
num_traits::One
来构建你需要的数字2,可以编写比Jmb的答案更通用的代码。这样,代码甚至可以处理整数(当然,有四舍五入)。字符串
当你想写通用的数字代码时,不要犹豫使用
num_traits
-这就是它的用途。你可以使用更强的绑定Num
来代替所有的单独操作:型