创建一个绑定到整数类型的通用函数
Creating a generic function bounded to integer types
在尝试学习 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));
}
现在我想使函数通用,以便我可以传递任何整数类型: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));
}
我看到广告中的 num
板条箱,看起来很合适。我期待 T: num::Integer
并完成,但我觉得我正在沿着兔子洞盘旋而下,我似乎无法获得正确的边界组合。
任何建议都会很棒!以及任何使我的代码更加地道的技巧也会有所帮助,谢谢。
终于到了。结果我需要使用 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>() * u8::BITS as usize;
(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
crate 实际上也有计算设置位数的功能 num::PrimInt::count_ones
。
在尝试学习 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));
}
现在我想使函数通用,以便我可以传递任何整数类型: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));
}
我看到广告中的 num
板条箱,看起来很合适。我期待 T: num::Integer
并完成,但我觉得我正在沿着兔子洞盘旋而下,我似乎无法获得正确的边界组合。
任何建议都会很棒!以及任何使我的代码更加地道的技巧也会有所帮助,谢谢。
终于到了。结果我需要使用 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>() * u8::BITS as usize;
(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
crate 实际上也有计算设置位数的功能 num::PrimInt::count_ones
。