我是否可以在泛型函数中使用原始类型的特征?

rus*_*oue 5 rust

我试图写一个通用的功能,这将尝试将字符串转换为数字类型一样i32,f64等等.如果字符串是不可自由兑换,然后将返回0.我正在寻找一个适合在我的通用函数中使用的特性:

use std::str::FromStr;

fn get_num_from_str<T: FromStr>(maybe_num_str: &String) -> T {
    let maybe_num = T::from_str(maybe_num_str.as_str());
    if maybe_num.is_ok() {
        return maybe_num.unwrap();
    }
    0 as T
}

fn main() {
    let num_str = String::from("12");
    println!("Converted to i32: {}", get_num_from_str::<i32>(&num_str));
}
Run Code Online (Sandbox Code Playgroud)

游乐场链接

我发现Rust有一个Primitive特征,之前被删除了.现在还有别的东西可以用吗?

我找到了一个解决方法:

use std::str::FromStr;

fn get_num_from_str<T: Default + FromStr>(maybe_num_str: &String) -> T {
    let maybe_num = T::from_str(maybe_num_str.as_str());
    maybe_num.unwrap_or(Default::default())
}
Run Code Online (Sandbox Code Playgroud)

游乐场链接

正如特征约束所暗示的那样,这应该适用于任何具有两者的实现的东西Default,FromStr并且我应该重命名该函数以反映这一点,但是知道是否只有原始数字类型的任何特征我仍然会很好用于确保此功能不能用于数字类型以外的任何其他功能.

U00*_*07D 9

Numnum crate中定义的特性应该满足你的需求,但是你想要做的事情在Rust中不是惯用的,所以我想提出两个建议:

  1. 例如,在像C这样的某些语言中,传统的方法是将具有特殊含义的特定值(例如0或-1)重载,但这已经被证明是混乱甚至是硬错误的根源.

相反,Result<T, E>如果您的函数由于多个原因而无法返回结果,或者Option<T>如果您的函数可能无法返回结果的确切原因之一,则请考虑使用该类型.

在您的情况下,您可能希望使用a,Result<T, E>因此您的函数可以传达转换失败的原因 - 字符串是否包含无效的数字字符?请求的类型的值是否超出范围?您的功能的呼叫者可能需要知道能够最好地处理这种情况.

  1. Rust标准库已经以std::string::String::parse()或者str::parse()方法的形式包含了您正在寻找的功能(通过通用实现将字符串转换为值).由于上面提到的原因,这些方法确实返回了a Result.

通过以上两条信息,您的代码现在可以更加健壮地重写如下(使用Rust 1.26+来简化错误处理):

type Result<T> = std::result::Result<T, Box<std::error::Error>>;

fn main() -> Result<()> {
    let num_str = String::from("12");
    println!("Converted to i32: {}", num_str.parse::<i32>()?);
    Ok(())
}
Run Code Online (Sandbox Code Playgroud)

操场的例子

如果出现问题,请注意报告的错误情况:

type Result<T> = std::result::Result<T, Box<std::error::Error>>;

fn main() -> Result<()> {
    let num_str = "-1";
    println!("Invalid u32 conversion: {}", num_str.parse::<u32>()?);
    Ok(())
}
Run Code Online (Sandbox Code Playgroud)

操场的例子

这将打印Error: ParseIntError { kind: InvalidDigit }到控制台并将值返回std::libc::EXIT_FAILURE给调用进程(表示程序退出并显示错误),所有这些都没有任何值重载或需要"幻数".

  • `fn main() - >结果<()>`我的生活现在已经完成 (2认同)

She*_*ter 6

不,没有这样的特质.为什么?因为Rust不需要像大多数其他语言那样关心将"原语"与"非原语"区分开来.实际上,为什么要这样呢?

另外,请注意数组原始指针也是基元; 你真的希望包括那些吗?

我可以使用它来确保此功能不能用于除数字类型之外的任何其他功能.

为什么你会想要人为地限制你可以使用什么类型?为什么您的功能不适用于满足其所需基本标准的任何类型?你是谁想保护自己?

你的例子可以缩短:

fn get_num_from_str<T: Default + FromStr>(s: &str) -> T {
    s.parse().unwrap_or_default()
}
Run Code Online (Sandbox Code Playgroud)