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

时间:2018-05-10 05:30:01

标签: rust

我正在尝试编写一个泛型函数,它会尝试将字符串转换为数字类型,如i32f64等。如果字符串不可转换,那么它将返回{{1} }。我正在寻找一个适合在我的通用函数中使用的特性:

0

Playground Link

我发现Rust有一个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)); } 特征,之前被删除了。现在还有别的东西可以用吗?

我找到了一个解决方法:

Primitive

Playground Link

正如特性限制所暗示的那样,这应该适用于任何具有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()) } Default实现的东西,我应该重命名该函数以反映这一点,但是知道是否仍然很好只有原始数字类型有任何特征,我可以使用它来确保此函数不能用于数字类型以外的任何其他类型。

2 个答案:

答案 0 :(得分:9)

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

  1. 在某些语言中,例如,传统的做法是将特定值(例如0或-1)重载为特殊含义,但这已经被证明是混乱甚至是错误的根源。
  2. 相反,如果您的函数由于多个原因而无法返回结果,请考虑使用Result<T, E>类型,如果您的函数可能无法使用Option<T>类型,则考虑使用Result<T, E>类型返回结果。

    在您的情况下,您可能希望使用Result,以便您的函数可以通知转换失败的原因 - 字符串是否包含无效的数字字符?请求的类型的值是否超出范围?您的职能的来电者可能需要知道能够最好地处理这种情况。

    1. Rust标准库已经以std::string::String::parse()str::parse()方法的形式包含您要查找的功能(通过通用实现将字符串转换为值)。出于上述原因,这些方法确实返回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(()) }
    2. 通过以上两条信息,您的代码现在可以更加健壮地重写如下(使用Rust 1.26+来简化错误处理):

      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 }

      playground example

      这会将std::libc::EXIT_FAILURE打印到控制台并将值<div class="row inview dragula clearfix"> <div class="col-md-12 clearfix"> <div class="box clearfix" style = "height:243px;border:4px dashed rgba(25,25,25,.5)"> <div class="box-body draggable handle"> Set Up </div> </div> </div> <div class="col-md-3 clearfix"> <div class="box " style = "height:243px;border:4px dashed rgba(25,25,25,.5)"> <div class="box-body draggable handle"> Shortcut </div> </div> </div> <div class="col-md-3 clearfix"> <div class="box" style = "height:243px;border:4px dashed rgba(25,25,25,.5)"> <div class="box-body draggable handle"> Shortcut 2 </div> </div> </div> <div class="col-md-9 "> <div class="box" style = "height:500px;border:4px dashed rgba(25,25,25,.5)"> <div class="box-body draggable handle"> Calendar </div> </div> </div> <div class="col-md-6 clearfix"> <div class="box " style = "height:243px;border:4px dashed rgba(25,25,25,.5)"> <div class="box-body draggable handle"> Report </div> </div> </div> </div> 返回给调用进程(表示程序退出并显示错误),所有这些都没有任何值重载或&#34;幻数&#34;必需的。

答案 1 :(得分:6)

不,没有这样的特质。为什么?因为Rust不需要关心区分&#34;原语&#34;来自&#34;非基元&#34;和大多数其他语言一样多。实际上,为什么要

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

  

我可以用它来确保这个函数不能用于数字类型以外的任何东西。

为什么您希望人为限制您可以使用的类型?为什么您的功能不适用于符合其所需基本标准的任何类型?你是谁试图保护自己?

你的例子可以缩短:

{{1}}