简体   繁体   English

Rust中具有有限已知类型的泛型函数?

[英]Generic functions in Rust with limited, known types?

I'm writing some code in Rust which can work equally as well with f64 and f32 . 我正在Rust中编写一些代码,它可以与f64f32

Attempting to convert this to use generic functions is quite involved; 尝试将其转换为使用泛型函数非常复杂; I need to declare the capabilities of the type on every use. 我需要在每次使用时声明该类型的功能。

In practice, I only want f32 and f64 to be used. 在实践中,我只希望使用f32f64 Is there a way to write generic functions that only apply to a set of known types? 有没有办法编写仅适用于一组已知类型的泛型函数?

I realize this goes against generic functions a little. 我意识到这有点违背泛型函数。

Just use the Float trait from the num crate . 只需使用num Crate中的Float特性即可 You'll have anything you need for both f32 and f64 only . f32f64您将拥有所需的任何东西。 Do not write your own trait if you don't really need to. 如果不需要,不要写自己的特征。

Just add the crate num-traits into your [dependencies] section of your Cargo.toml file to be able to use that trait: 只需将板条箱num-traits添加到Cargo.toml文件的[dependencies]部分中即可使用该特征:

[dependencies]
# ...
num-traits = "0.1"

The only tool that comes to mind for this is a trait , so your function would be: 想到的唯一工具是trait ,因此您的功能将是:

pub fn f<T: MyTrait>(x: T) {...}

You could then implement MyTrait for f32 and f64 . 然后,您可以实现MyTraitf32f64 This is close, but there's a hole: callers can implement the trait on their own types. 这很接近,但有一个漏洞:调用者可以在自己的类型上实现该特征。 You can't get around this by making MyTrait private, since Rust then complains that you're using a private type ( MyTrait ) in a public interface. 您不能通过将MyTrait私有来解决此问题,因为Rust随后抱怨您在公共界面中使用了私有类型( MyTrait )。

So close, but I don't think it's exactly possible! 如此接近,但我认为这是完全不可能的!

Although I agree with the other answer about using an existing relevant trait, you would do it a bit like: 尽管我同意关于使用现有相关特征的其他答案,但是您可以这样做:

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
}

It might not be ideal, but I accomplish this by using a trait and a macro. 这可能并不理想,但是我可以通过使用特征和宏来实现。

For example, say we want this function to take either f32 or f64 : 例如,假设我们希望此函数采用f32f64

fn sqr(a: f32) -> f32 {
    a * a
}

We can first put it in a trait: 我们首先可以将其置于特征中:

trait Sqr {
    fn sqr(self) -> Self;
}

Then we make a macro for implementing it. 然后我们创建一个宏来实现它。 The macro just takes a type, and implements the trait for that type: 宏只接受一个类型,并实现该类型的特征:

macro_rules! impl_sqr {
    ($t:ty) => (
        impl Sqr for $t {
            fn sqr(self) -> Self {
                self * self
            }
        }
    );
}

Then we call the macro for f32 and f64 : 然后我们调用f32f64的宏:

impl_sqr!(f32);
impl_sqr!(f64);

Full example here. 完整示例在这里。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM