特征是否可能对其实现的类型的引用施加限制?

时间:2017-10-24 21:54:24

标签: rust

我正在尝试编写一个将Integer减半的泛型函数。为了记录,我知道有一个num_integer::Integer特征,我在我的真实代码中使用它。

为了减半,我Integer所需的唯一操作就是能够将引用移到右边和一个值。我想在很多地方使用Integer,所以我在Integer特征中捕获这两个特征并为其提供通用实现。但是,我仍然需要为std::ops::Shr函数指定half

我知道这个问题有两种解决方法。一种是在任何地方指定std::ops::Shr

extern crate num_traits;

pub trait Integer
where
    Self: num_traits::One,
    for<'a> &'a Self: std::ops::Shr<Self, Output = Self>,
{
}

impl<T> Integer for T
where
    T: num_traits::One,
    for<'a> &'a T: std::ops::Shr<T, Output = T>,
{
}

fn half<N: Integer>(n: &N) -> N
where
    for<'a> &'a N: std::ops::Shr<N, Output = N>, // Would like to get rid of this line!
{
    n >> num_traits::one()
}

fn main() {
    println!("{}", half(&85));
}

另一个选择是让half使用它的参数而不是借用它,在这种情况下,我正在改变值而不是引用,并且不再需要使用违规的注释行:

extern crate num_traits;

pub trait Integer
where
    Self: num_traits::One,
    Self: std::ops::Shr<Self, Output = Self>,
{
}

impl<T> Integer for T
where
    T: num_traits::One,
    T: std::ops::Shr<T, Output = T>,
{
}

fn half<N: Integer>(n: N) -> N {
    n >> num_traits::one()
}

fn main() {
    println!("{}", half(85));
}

还有其他一些我未考虑的选择吗?

1 个答案:

答案 0 :(得分:1)

另一种方法是将函数移动到特征方法:

pub trait Integer
where
    Self: num_traits::One,
    for<'a> &'a Self: std::ops::Shr<Self, Output = Self>,
{
    fn half(&self) -> Self {
        self >> num_traits::one()
    }
}

这不是真正解决核心问题,但它确实可以让你避免再次编写那个绑定。