【问题标题】:Is there any way to restrict a generic type to one of several types?有没有办法将泛型类型限制为几种类型之一?
【发布时间】:2016-11-23 23:47:59
【问题描述】:

我正在尝试创建一个通用结构,它使用“整数类型”来引用数组。出于性能原因,我希望能够轻松指定是否使用u16u32u64。像这样的东西(这显然不是有效的 Rust 代码):

struct Foo<T: u16 or u32 or u64> { ... }

有什么办法可以表达吗?

【问题讨论】:

    标签: rust


    【解决方案1】:

    对于数组的引用,通常您只需使用 usize 而不是不同的整数类型。

    但是,要在创建新 trait 后做自己的事情,请为 u16u32u64 实现该 trait,然后将 T 限制为您的新 trait。

    pub trait MyNewTrait {}
    
    impl MyNewTrait for u16 {}
    impl MyNewTrait for u32 {}
    impl MyNewTrait for u64 {}
    
    struct Foo<T: MyNewTrait> { ... }
    

    您还可以在MyNewTraitimpls 上添加方法来封装特定于u16u32u64 的逻辑。

    【讨论】:

    • 是的,但这并不能让我做我可以用 u16、u32 或 u64 做的所有事情——例如我无法使用值来检索数组的元素、比较两个值等。
    • @HenningKoehler:你可以,你只需要在特征级别声明它。那是pub trait MyNewTrait: Add&lt;Output = Self&gt; + Mul&lt;Output = Self&gt; + ... {}
    • 我想,但这也很快变得乏味......并且为了引用向量,我需要转换为 usize,这对于可以添加的任意类型似乎不太安全,相乘等等...
    • @HenningKoehler 您可以为Into&lt;usize&gt; 的结构或特征添加另一个特征限制。 T: MyNewTrait + Into&lt;usize&gt;trait MyNewTrait : Into&lt;usize&gt;
    【解决方案2】:

    有时您可能希望使用enum 而不是具有特征绑定的泛型类型。例如:

    enum Unsigned {
        U16(u16),
        U32(u32),
        U64(u64),
    }
    
    struct Foo { x: Unsigned, ... };
    

    与为现有类型实现新特征相比,创建新类型的一个优点是您可以将外来特征和固有行为添加到新类型。您可以为Unsigned 实现任何您喜欢的特征,例如AddMul 等。当Foo 包含Unsigned 时,在Unsigned 上实现特征不会影响Foo 的签名,例如它会将它们添加为Foo 参数的边界(例如Foo&lt;T: Add&lt;Output=Self&gt; + PartialCmp + ...&gt;)。另一方面,您仍然必须实现每个特征。

    另一件需要注意的事情:虽然你通常可以创建一个新类型并为它实现一个特征,但枚举是“关闭的”:你不能在不触及其实现的其余部分的情况下向Unsigned 添加新类型,就像你使用特质一样。这可能是好事也可能是坏事,具体取决于您的设计要求。


    “性能原因”有点模棱两可,但如果您考虑存储大量 Unsigneds,它们都将是相同的内部类型,那么:

    struct Foo([Unsigned; 1_000_000]);
    

    存储一百万个u16s 会浪费大量空间,您仍然可以将Foo 设为通用!只需为 Unsigned 实现 From&lt;u16&gt;From&lt;u32&gt;From&lt;u64&gt;,然后改写:

    struct Foo<T: Into<Unsigned>>([T; 1_000_000]);
    

    现在您只在T 上绑定了一个简单的特征,您不会为标签和填充浪费空间,并且处理T 的函数始终可以将其转换为Unsigned 以进行计算。甚至可以完全优化转换成本。

    另见

    【讨论】:

    • 天啊。正是我正在寻找的哈哈。我没有意识到我可以以这种方式在枚举中使用元组结构,但现在我想它真的很有意义。
    • 只是补充一点,num 板条箱已经为您完成了这项工作:docs.rs/num/latest/num/traits/trait.Unsigned.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 2021-03-28
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多