【问题标题】:Generic functions in Rust with limited, known types?Rust 中具有有限已知类型的泛型函数?
【发布时间】:2016-08-22 08:33:20
【问题描述】:

我正在用 Rust 编写一些代码,这些代码与 f64f32 一样好。

尝试将其转换为使用泛型函数非常复杂;我需要在每次使用时声明该类型的功能。

在实践中,我只希望使用f32f64。有没有办法编写只适用于一组已知类型的泛型函数?

我意识到这有点违背泛型函数。

【问题讨论】:

    标签: generics types rust


    【解决方案1】:

    只需使用the Float trait from the num cratef32f64 only 都能满足您的所有需求。如果你真的不需要,不要写你自己的特质。

    只需将 crate num-traits 添加到 Cargo.toml 文件的 [dependencies] 部分即可使用该特征:

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

    【讨论】:

    • 仅适用于 f32f64 — 这仅适用于特定时间点和一组特定的 crate。 anyone 完全有可能实现一个实现 Float 特征的类型,然后将其传递给函数。
    【解决方案2】:

    为此想到的唯一工具是trait,所以你的函数是:

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

    然后您可以为f32f64 实现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
    }
    

    【讨论】:

    • 我实际上认为自定义特征可能会更好,具体取决于上下文。这一切都取决于如何使用该值以及需要什么样的方法。自定义 trait 只是 the interface segregation principle 的一种表现形式。
    • 执行fn sqr&lt;T: MyTrait&gt;(x: T) -&gt; T { x * x } 错误给出error: binary operation `*` cannot be applied to type `T`
    • 您还需要指定 T 需要实现的其他特征,例如 T:MyTrait+Mul&lt;T&gt; 以允许乘法。
    【解决方案3】:

    这可能并不理想,但我通过使用特征和宏来实现这一点。

    例如,假设我们希望此函数采用f32f64

    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
                }
            }
        );
    }
    

    然后我们调用f32f64 的宏:

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

    Full example here.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多