Generics 是否可以在Rust中编写通用整数长度函数?

Generics 是否可以在Rust中编写通用整数长度函数?,generics,rust,Generics,Rust,我为u32编写了一个长度函数。我可以很容易地复制/粘贴/编辑到其他int类型,但是当我尝试使用泛型时,我就卡住了。有没有我误解的概念 传递长度函数 fn len_int(n: u32) -> u32 { // 0 std::iter::repeat_with({ let mut l = 0; // can't call pow on ambiguous numeric type move || match n / 10u32.pow(

我为
u32
编写了一个长度函数。我可以很容易地复制/粘贴/编辑到其他int类型,但是当我尝试使用泛型时,我就卡住了。有没有我误解的概念

传递长度函数

fn len_int(n: u32) -> u32 { // 0
    std::iter::repeat_with({
        let mut l = 0;
        // can't call pow on ambiguous numeric type
        move || match n / 10u32.pow(l) { // 1
            0 => 0,
            _ => {
                l += 1;
                1
            }
        }
    })
        .take_while(|&x| x != 0)
        // count returns usize
        .count() as u32 // 2
}
一个失败的通用长度函数:I

fn len_int<T>(n: T) -> T
where
    T: Copy + Clone,
{
    std::iter::repeat_with({
        let mut l = 0;
        move || match n / 10.pow(l) {
            //1
            0 => 0,
            _ => {
                l += 1;
                1
            }
        }
    })
    .take_while(|&x| x != 0)
    .count() at T // 2
}
fn len_int(n:T)->T
哪里
T:复制+克隆,
{
标准:国际热核实验堆:重复({
设mutl=0;
移动| |匹配n/10。功率(l){
//1
0 => 0,
_ => {
l+=1;
1.
}
}
})
.take|while(|&x|x!=0)
T//2处的.count()
}
编译器告诉我我不能
在不明确的数值类型{integer}上调用方法pow
无法按类型错误划分T
或者将
count()
转换为T,因为T不是基元类型。

您的脑海中可能有特定的类型,但编译器不知道这一点。对于编译器来说,泛型类型
T
可以是任何类型。它可以是一个字符串。它可以是对函数指针的引用。它可以是文件句柄的向量。任何东西因此,您的代码需要同时处理所有这些可能的类型

要使用更具体的类型,必须提前声明希望该类型支持的所有内容。编译器不允许您使用任何未声明的操作


Rust的标准库中没有
.pow
的特性,因此您不能在开箱即用的情况下声明它。您可以自己制作一个,也可以使用。

我们可以定义一个特征,然后为您希望在泛型函数中支持的具体类型实现该特征:

pub trait IntLenExt<T> {
    fn is_divis(&self, power: u32) -> bool;
    fn cast_count(count: usize) -> T;
}

impl IntLenExt<u32> for u32 {
    fn is_divis(&self, power: u32) -> bool {
        self / 10u32.pow(power) == 0
    }

    fn cast_count(count: usize) -> u32 {
        count as u32
    }
}

impl IntLenExt<u64> for u64 {
    fn is_divis(&self, power: u32) -> bool {
        self / 10u64.pow(power) == 0
    }

    fn cast_count(count: usize) -> u64 {
        count as u64
    }
}

fn len_int<T>(n: T) -> T
where
    T: Copy + Clone + IntLenExt<T>,
{
    T::cast_count(std::iter::repeat_with({
        let mut l = 0;
        move || match n.is_divis(l) {
            //1
            true => 0,
            false => {
                l += 1;
                1
            }
        }
    })
    .take_while(|&x| x != 0)
    .count()) // 2
}


fn main() {
    let input: u64 = 100;
    println!("len_int({}) => {}", input, len_int(input));
}
pub trait IntLenExt{
fn是_divis(&self,power:u32)->bool;
fn cast_count(count:usize)->T;
}
u32的impl IntLenExt{
fn是_divis(&self,power:u32)->bool{
自身/10u32.pow(功率)==0
}
fn铸造计数(计数:usize)->u32{
算作u32
}
}
u64的impl IntLenExt{
fn是_divis(&self,power:u32)->bool{
自身/10u64.pow(功率)==0
}
fn铸造计数(计数:usize)->u64{
算作u64
}
}
fn len_int(n:T)->T
哪里
T:Copy+Clone+IntLenExt,
{
T::投射计数(标准::iter::重复({
设mutl=0;
移动| |匹配n.is|u divis(l){
//1
true=>0,
假=>{
l+=1;
1.
}
}
})
.take|while(|&x|x!=0)
.count())//2
}
fn main(){
let输入:u64=100;
println!(“len_int({})=>{}”,输入,len_int(输入));
}

它是如何/在哪里失败的?包括错误消息和详细信息。提供的游乐场链接导致完全不同的代码…@jmb,很抱歉有时会发生这种情况,请忘记检查它。它现在可以工作了。有关处理泛型整数类型的详细信息,请参阅。另外,一些指数数学告诉我,无论传入什么整数,都不会溢出
usize
,这就是
.count()
返回的值。因此,您确实应该返回
usize
。此外,计算一个数字在给定基数中所占位数(本例中为10)的最简单方法是将该数字记录在该基数中。在这种情况下,记录x的底10。然后,把它的上限设为一个整数。例子: