首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >是否有一个只能在泛型函数中使用的基本类型的特征?

是否有一个只能在泛型函数中使用的基本类型的特征?
EN

Stack Overflow用户
提问于 2018-05-10 13:30:01
回答 1查看 3.2K关注 0票数 7

我正在尝试编写一个泛型函数,它将尝试将字符串转换为数字类型,如i32f64等。如果字符串不可转换,则它将返回0。我正在寻找一个合适的特征,并在下面的泛型函数中使用:

代码语言:javascript
复制
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));
}

Playground Link

我发现Rust有一个Primitive特征,在此之前它被移除了。现在有没有其他可以替代的东西呢?

我找到了一种解决方法:

代码语言:javascript
复制
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())
}

Playground Link

正如特征界限所暗示的那样,这应该适用于同时具有DefaultFromStr实现的任何东西,我应该重命名该函数以反映这一点,但如果知道是否存在仅用于原始number类型的特征,以确保此函数不能用于除number类型之外的任何其他类型,则仍然很好。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-05-10 14:28:44

num crate中定义的Num特征应该可以满足您的需求,但是您尝试做的事情在Rust中并不是惯用的,所以我想提供两个建议:

  1. 在某些语言中,例如C语言,传统上是用特殊含义重载像0或-1这样的特定值,但这已被证明是混乱甚至严重错误的根源。

相反,如果您的函数可能由于多种原因而无法返回结果,请考虑使用Result<T, E>类型,或者如果您的函数可能无法返回结果只有一个原因,请考虑使用Option<T>类型。

在本例中,您可能希望使用Result<T, E>,这样您的函数就可以说明转换失败的原因--字符串是否包含无效的数字字符?该值是否超出所请求类型的范围?函数的调用者可能需要知道才能最好地处理这种情况。

Rust

  • 标准库已经以std::string::String::parse()str::parse()方法的形式包含了您正在寻找的功能(通过泛型实现将字符串转换为值)。由于上述原因,这些方法确实会返回一个Result.

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

代码语言:javascript
复制
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(())
}

playground example

如果出现问题,请注意报告错误的方式有多好:

代码语言:javascript
复制
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(())
}

playground example

这会将Error: ParseIntError { kind: InvalidDigit }输出到控制台,并将值std::libc::EXIT_FAILURE返回给调用进程(表示程序退出时出现错误),而不需要任何值重载或“幻数”。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50266085

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档