我想定义一个函数,该函数可以返回在调用函数时指定其类型的数字。该函数需要一个缓冲区(Vec<u8>
)并返回数字值,例如
let byte = buf_to_num<u8>(&buf);
let integer = buf_to_num<u32>(&buf);
缓冲区包含一个表示数字的ASCII字符串,例如b"827"
,其中每个字节都是一个数字的ASCII码。
这是我的无效代码:
extern crate num;
use num::Integer;
use std::ops::{MulAssign, AddAssign};
fn buf_to_num<T: Integer + MulAssign + AddAssign>(buf: &Vec::<u8>) -> T {
let mut result : T;
for byte in buf {
result *= 10;
result += (byte - b'0');
}
result
}
我在加法和乘法行(expected type T, found u32
)上都得到了不匹配的类型错误。因此,我想我的问题是如何告诉类型系统T
可以用文字10
还是(byte - b'0')
的结果来表示?
答案 0 :(得分:2)
欢迎您不必指定您要用作泛型的每个操作。这很痛苦,但值得。
您有两个问题:
result *= 10;
,但没有相应的From<_>
定义。这是因为,当您指定“ 10”时,编译器无法知道T
代表的“ 10”是什么-它知道原始类型,以及通过实现From<_>
定义的任何转换特质我们需要为此做两个假设:
我们将需要From<u32>
,因此我们可以将数字限制为u32
我们还将阐明您的逻辑并将每个u8
转换为char
,以便我们可以使用to_digit()
将那个转换为{{1} },然后再使用u32
获得From<u32>
。
T
您可以使自己相信其行为on the playground
通过将常数强制转换为use std::ops::{MulAssign, AddAssign};
fn parse_to_i<T: From<u32> + MulAssign + AddAssign>(buf: &[u8]) -> T {
let mut buffer:T = (0 as u32).into();
for o in buf {
buffer *= 10.into();
buffer += (*o as char).to_digit(10).unwrap_or(0).into();
}
buffer
}
来解决乘法问题,这使它受益于我们对T的u8
的要求,并使rust编译器知道我们没有做傻事。
最后的更改是将From<u8>
设置为默认值0。
让我知道这对您是否有意义(或者是否不可行),如果有问题,我很乐意进一步阐述:-)