generics - 有没有一种方法可以实现与泛型相结合的 `as`语义?

标签 generics rust

我正在尝试将通用字符串写入Rust中的数字函数,其中支持的类型为i16i32i64u32u64f32f64
最初我有这个:

fn str_to_num<N>(s: &str, default_res: N) -> N
where
    N: FromStr,
{
    if let Ok(n) = N::from_str(s) {
        return n;
    }
    default_res
}

在我被要求也支持十六进制字符串之前,这种方法工作得很好。
由于我们只想将十六进制字符串解析为整数,所以我现在有两个版本的函数:
use std::convert::TryFrom;
use std::str::FromStr;

fn str_to_num_with_hex<N>(s: &str, default_res: N) -> N
where
    N: FromStr + TryFrom<u64>,
{
    if s.starts_with("0x") || s.starts_with("0X") {
        if let Ok(n) = u64::from_str_radix(&s[2..], 16) {
            if let Ok(n) = N::try_from(n) {
                return n;
            }
        }
    }
    return str_to_num(s, default_res);
}

fn str_to_num<N>(s: &str, default_res: N) -> N
where
    N: FromStr,
{
    if let Ok(n) = N::from_str(s) {
        return n;
    }
    default_res
}

但是,当使用适合u64而不适合i64的十六进制字符串测试该函数时,TryFromas的行为似乎有所不同。有没有一种方法可以实现将as语义与泛型结合起来?
fn main() {
    let hex = "0xB85991EE5DA2B557";
    let unsigned_long: u64 = str_to_num_with_hex(hex, 0);
    let signed_long: i64 = str_to_num_with_hex(hex, 0);
    println!("{}", unsigned_long); // prints 13283809028865176919
    println!("{}", signed_long); // prints 0
    println!("{}", unsigned_long as i64); // prints -5162935044844374697
}

最佳答案

我不这么认为。 as字面意义上不会失败,遗憾的是,为了方便起见并与现有语言保持一致,Rust决定实现as来进行可能有损的数字转换,例如isize as u8
try_from实际上可能会失败,这就是重点。因此,如果遇到有损转换(输入超出范围),它将失败,这很重要。

我建议为自己想要的语义创建自己的特征,例如

trait FromHex where Self: Sized {
    fn from_hex(s: &str) -> Option<Self>;
}

impl FromHex for u64 {
    fn from_hex(s: &str) -> Option<u64> {
        u64::from_str_radix(s, 16).ok()
    }
}
impl FromHex for i64 {
    fn from_hex(s: &str) -> Option<i64> {
        u64::from_hex(s).map(|v| v as i64)
    }
}

fn main() {
    let s = "B85991EE5DA2B557";
    println!("{:?} {:?}", u64::from_hex(s), i64::from_hex(s));
}

conv也许也可以开箱即用地完成您想做的事情。

关于generics - 有没有一种方法可以实现与泛型相结合的 `as`语义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61269025/

相关文章:

java - 组合两个通用列表

rust - 如何使 Debug 在 no_std 代码中发出十六进制值?

rust - 我的 EXTI0 中断处理程序没有被覆盖/正常工作(STM32F3Discovery)

rust - 如何在 where 子句中使用关联常量?

c# - 从Rust向C#DLL发送数据时发生STATUS_HEAP_CORRUPTION错误

rust - 有没有办法在文档注释中内联常量(由 cargo 文档呈现)?

谓词接口(interface)中的 Java 泛型方法

c++ - 错误C++: ‘const_iterator’没有命名类型;

vb.net - 如何在vb.net中创建T类型的对象

generics - 什么特征告诉编译器 `T` 是具有隐式复制的简单类型?