将通用类型限制为基本数字类型

时间:2019-06-11 02:58:25

标签: rust

我们可以通过where clause将类型限制为一个或多个特征。

我的问题是:

  • 是否可以将类型限制为仅原始数字类型?

  • 如何?

3 个答案:

答案 0 :(得分:2)

否。

要使用参数类型,您需要特征来定义要在其上调用的有效操作。因此,您需要具有要调用的所有操作的一个或多个特征。

Rust中的“原始”类型并不特殊。就像任何“非原始”数字类型一样,它们通过std::ops的特征(尽管显然使用编译器内部函数)来定义其运算符。

实际上,“原始”和“非原始”数字类型之间的界限甚至有些模糊,因为对于缺少FPU的目标,标准库可能正在代码中实现浮点类型,而在Rust中,它可以对用户透明地进行操作。

实际上,没有原始数字类型。号码类型是通过提供您需要呼叫的任何运算符来定义的。因此,只需通过std::ops特征限制您的类型。

答案 1 :(得分:1)

如果您将特征视为编译时鸭子输入,那么一个更好的问题将是:您要在 number 中寻找的确切特征是什么?可以将对它们的大多数操作定义为您类型的特征约束,请参阅:the standard operator traits

即使您要在外部包装箱中定义特征并仅在该外部包装箱中实现特定类型的行为,也要考虑到特征实施规则将在此处为您提供帮助(即,只有在以下情况下,特征才能实施为一种类型)特质或类型,或两者都在您当前的箱子中)仍然不会限制任何人为自己的类型实施您的特质。

因此,我没有其他选择,只能为每个原始数字类型实现没有泛型的行为。为了避免代码重复,我可能会为此使用宏-毕竟,如果您以某种方式考虑它,则可以手动执行编译器在使通用代码单态化时所做的工作。

话虽这么说,但我没有理由将行为限制在数字上,而不仅限于某些特征,我会像在第一段中所述那样依靠它们。

答案 2 :(得分:1)

由于基元不是特征类型,因此不能用作限制通用类型的边界。但是您可以直接为特定类型实现:

struct Struct<T>(T);

trait Printer {
    fn print(&self);
}

impl Printer for Struct<i32> {
    fn print(&self) {
        println!("Printing for i32 value: {}", self.0);
    }
}

fn main() {
    let x = Struct(15_i32);
    let _z = Struct(14.2_f64);

    x.print();
    //_z.print();//compile error
}

Playground

或者,您可以使用Borrow<S>特性作为技巧,可以按如下所示限制您的通用参数:(T: Borrow<S>意味着T可以借来作为S)。

impl<T> Printer for Struct<T>
where
    T: Borrow<f64> + Debug,
{
    fn print(&self) {
        println!("Printing for f64 value: {:?}", self.0);
    }
}

Playground

但是由于您可以为任何类型实现Borrow<f64>,因此这种限制可能并不严格。

对于数字原语,您也可以使用num-traits板条箱中的特征,例如ToPrimitive AsPrimitive