一个别名较高的性状可以绑定到锈吗?

时间:2019-05-25 16:44:46

标签: rust

我的程序有许多对通用整数进行运算的函数。它们通常具有以下形式:

use num::{FromPrimitive, Integer, ToPrimitive};
use std::cmp::Ord;
use std::ops::{Add, Mul};

fn function<'a, I>(n: &'a I) -> I
where
    I: Integer + Clone + FromPrimitive + ToPrimitive,
    for<'b> &'b I: Mul<Output = I> + Add<Output = I> + Ord,
{

}

我想别名通用类型要求:

I: Integer + Clone + FromPrimitive + ToPrimitive,
for<'b> &'b I: Mul<Output = I> + Add<Output = I> + Ord,

这样我就不需要每次都重写它们。最初,我认为宏会有所帮助,但看起来它们在C语言中不起作用,所以我寻找了另一种方法。

我找到了满足第一个要求的方法。必须在任何类型T上对定义的特征应用默认实现。

trait GInteger: Integer + Clone + FromPrimitive + ToPrimitive {}
impl<T: Integer + Clone + FromPrimitive + ToPrimitive> GInteger for T {}

然后我可以简单地写:

I: GInteger

代替

I: Integer + Clone + FromPrimitive + ToPrimitive,

如何别名第二个要求?有可能吗?

for<'b> &'b I: Mul<Output = I> + Add<Output = I> + Ord,

1 个答案:

答案 0 :(得分:1)

不,不能为此使用新特征。

虽然可以将第二个要求包括在特征定义中...

trait GInteger: Integer + Clone + FromPrimitive + ToPrimitive
where
    for<'b> &'b Self: Mul<Output = Self> + Add<Output = Self> + Ord,
{
}

rustc不会为您详细说明where子句,因此在function()的声明中,您仍然需要编写where for<'b> &'b I: ...绑定。这是known bug

fn function<I: GInteger>(n: &I) -> I
where
    for<'b> &'b I: Mul<Output = I> + Add<Output = I> + Ord,  // meh
{
    n * n
}

如果您使用每晚的Rust,则可以改用trait alias (RFC 1733),从而完全解决了这个问题。

#![feature(trait_alias)]

use num::{FromPrimitive, Integer, ToPrimitive};
use std::cmp::Ord;
use std::ops::{Add, Mul};

// Define a trait alias
trait GInteger = Integer + Clone + FromPrimitive + ToPrimitive
where
    for<'b> &'b Self: Mul<Output = Self> + Add<Output = Self> + Ord;

// Just use it
fn function<I: GInteger>(n: &I) -> I {
    n * n
}