创建绑定到整数类型的泛型函数

时间:2019-11-08 22:05:43

标签: generics rust traits

在尝试学习防锈技术时,我从一些基本练习开始。 我写了一个简单的函数,希望能用惯用的锈来计数整数中设置的位数。

fn bit_count(x: u32) -> u32 {
    (0..32).into_iter().map(|i| (x >> i) & 1).sum()
}

fn main() {
    println!("{} has {} set bits.", 5, bit_count(5));
}

现在,我想使函数通用,以便可以传递任何整数类型:i32u32i64u64 ...等。

我对C ++中的tmp非常熟悉,但是我尝试使用rust泛型失败了,到目前为止,我有这个:

extern crate num;

fn bit_count<T>(x: T) -> T
where
    T: num::Integer + std::ops::BitAnd + std::ops::Shr + num::NumCast,
    std::ops::Range<T>: std::iter::IntoIterator,
{
    (T::zero()..num::NumCast::from(32).unwrap())
        .into_iter()
        .map(|i| (x >> num::NumCast::from(i)) & T::one())
        .sum()
}

fn main() {
    println!("{} has {} set bits.", 5, bit_count(5));
}

我看到了num条板条箱的广告,这似乎很合适。我原本希望T: num::Integer能够完成,但是我感觉自己在这里钻一个兔子洞,似乎无法获得正确的边界组合。

任何建议都会很棒!谢谢,所有使我的代码更加习惯的技巧也将有所帮助。

1 个答案:

答案 0 :(得分:1)

最后到达那里。事实证明,我需要使用num::PrimInt特性作为绑定,因为它包含所有按位运算和强制转换。 num::Integer的约束较少,并且在纯数学意义上对整数建模,因此没有按位运算。

我的最终代码如下:

extern crate num;

fn bit_count<T>(x: T) -> T
where
    T: num::PrimInt + std::iter::Sum,
{    
    let n_bits = std::mem::size_of::<T>() * 8;
    (0..n_bits).into_iter().map(|i| (x >> i) & T::one()).sum()

}

fn main() {
    println!("{} has {} set bits.", 5, bit_count(5u32));
    println!("{} has {} set bits.", 5, bit_count(5i32));
    println!("{} has {} set bits.", 5, bit_count(5i64));
}

不需要T::one()很高兴,但是似乎没有办法解决。此外,在我的工作范围内,还需要std::iter::Sum特性以允许正常工作流程。

num板条箱实际上也具有对设置的位数进行计数的功能num::PrimInt::count_ones