【发布时间】:2016-08-22 08:33:20
【问题描述】:
我正在用 Rust 编写一些代码,这些代码与 f64 和 f32 一样好。
尝试将其转换为使用泛型函数非常复杂;我需要在每次使用时声明该类型的功能。
在实践中,我只希望使用f32 和f64。有没有办法编写只适用于一组已知类型的泛型函数?
我意识到这有点违背泛型函数。
【问题讨论】:
我正在用 Rust 编写一些代码,这些代码与 f64 和 f32 一样好。
尝试将其转换为使用泛型函数非常复杂;我需要在每次使用时声明该类型的功能。
在实践中,我只希望使用f32 和f64。有没有办法编写只适用于一组已知类型的泛型函数?
我意识到这有点违背泛型函数。
【问题讨论】:
只需使用the Float trait from the num crate。 f32 和 f64 only 都能满足您的所有需求。如果你真的不需要,不要写你自己的特质。
只需将 crate num-traits 添加到 Cargo.toml 文件的 [dependencies] 部分即可使用该特征:
[dependencies]
# ...
num-traits = "0.1"
【讨论】:
f32 和 f64 — 这仅适用于特定时间点和一组特定的 crate。 anyone 完全有可能实现一个实现 Float 特征的类型,然后将其传递给函数。
为此想到的唯一工具是trait,所以你的函数是:
pub fn f<T: MyTrait>(x: T) {...}
然后您可以为f32 和f64 实现MyTrait。这很接近,但有一个漏洞:调用者可以在他们自己的类型上实现特征。您无法通过将MyTrait 设为私有来解决此问题,因为 Rust 会抱怨您在公共接口中使用私有类型 (MyTrait)。
如此接近,但我认为这不太可能!
虽然我同意另一个关于使用现有相关特征的答案,但你会这样做:
mod foo {
pub trait MyTrait {}
impl MyTrait for f32 {}
impl MyTrait for f64 {}
pub fn f<T: MyTrait>(x: T) {}
}
pub fn main() {
foo::f(3f32);
foo::f(3f64);
// foo::f(3u64); // doesn't work as u64 doesn't implement MyTrait
}
【讨论】:
fn sqr<T: MyTrait>(x: T) -> T { x * x } 错误给出error: binary operation `*` cannot be applied to type `T`
T:MyTrait+Mul<T> 以允许乘法。
这可能并不理想,但我通过使用特征和宏来实现这一点。
例如,假设我们希望此函数采用f32 或f64:
fn sqr(a: f32) -> f32 {
a * a
}
我们可以先把它放在一个特质中:
trait Sqr {
fn sqr(self) -> Self;
}
然后我们制作一个宏来实现它。宏只接受一个类型,并实现该类型的特征:
macro_rules! impl_sqr {
($t:ty) => (
impl Sqr for $t {
fn sqr(self) -> Self {
self * self
}
}
);
}
然后我们调用f32 和f64 的宏:
impl_sqr!(f32);
impl_sqr!(f64);
【讨论】: