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

nit*_*oid 5 generics traits rust

在我尝试学习 Rust 的过程中,我从一些基本练习开始。我写了一个简单的函数,我希望它是惯用的 rust 来计算整数中设置位的数量。

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));
}
Run Code Online (Sandbox Code Playgroud)

现在我想让函数通用,以便我可以传递任何整数类型:i32, u32, i64, u64... 等。

我对 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));
}
Run Code Online (Sandbox Code Playgroud)

我看到num板条箱的广告,它看起来很合适。我期待已经T: num::Integer完成并完成,但是我觉得我在这里陷入了一个兔子洞,我似乎无法获得正确的边界组合。

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

nit*_*oid 5

最后到了那里。结果我需要使用num::PrimInttrait 作为我的边界,因为它包括所有的按位操作和强制转换。该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));
}
Run Code Online (Sandbox Code Playgroud)

不需要它会很好,T::one()但似乎没有办法解决它。此外,std::iter::Sum在我的范围内需要 trait 以允许功能性工作流程。

num箱子实际上有一个函数来设置位计数的人数太多num::PrimInt::count_ones