如何将 FromStrRadixErr 转换为 ParseIntError?

ste*_*935 5 error-handling rust

我正在尝试围绕std::<T>::from_str_radix. 根据文档,from_str_radix返回Result<T, ParseIntError>. 但

fn foo<T: num_traits::Num>() -> Result<T, std::num::ParseIntError> {
    T::from_str_radix("4242", 10)
}
Run Code Online (Sandbox Code Playgroud)

不会编译:

错误:类型不匹配:预期core::result::Result<T, core::num::ParseIntError>,发现core::result::Result<T, <T as num_traits::Num>::FromStrRadixErr>

另一方面,这

fn main() {
    let x: Result<u8, std::num::ParseIntError> = foo();
    println!("{:?}", x);
}

fn foo<T: num_traits::Num>() -> Result<T, <T as num_traits::Num>::FromStrRadixErr> {
    T::from_str_radix("4242", 10)
}
Run Code Online (Sandbox Code Playgroud)

编译良好并打印预期结果

错误(ParseIntError {种类:溢出})

在我看来,两者的情况相同,但显然我错了。有人可以向我解释其中的差异并可能向我展示解决方案吗?

mal*_*rbo 3

如何转换FromStrRadixErrParseIntError

这是不可能的。有些错误(例如io::Error)允许您创建一个包含导致错误的实例,因此您可以创建一个包含另一个错误的错误。如果ParseIntError有这样的功能,您可能会创建一个ParseIntError导致FromStrRadixErr错误的结果,但ParseIntError事实并非如此。

有人可以向我解释其中的区别吗?

这段代码:

fn foo<T: num_traits::Num>() -> Result<T, std::num::ParseIntError> {
    T::from_str_radix("4242", 10)
}
Run Code Online (Sandbox Code Playgroud)

无法编译,因为返回的类型T::from_str_radix不是。将返回类型(如您所做的那样)更改为,可以解决问题。Result<T, FromStrRadixErr>Result<T, ParseIntError>Result<T, FromStrRadixErr>

这段代码:

fn main() {
    let x: Result<u8, std::num::ParseIntError> = foo();
    println!("{:?}", x);
}

fn foo<T: num_traits::Num>() -> Result<T, <T as num_traits::Num>::FromStrRadixErr> {
    T::from_str_radix("4242", 10)
}
Run Code Online (Sandbox Code Playgroud)

编译良好,因为DefinesNum的特征实现。u8 FromStrRadixErr = ParseIntError

如果您更改u8f32

let x: Result<f32, std::num::ParseIntError> = foo();
Run Code Online (Sandbox Code Playgroud)

它无法编译。Num其实现f32 定义 FromStrRadixErr = ParseFloatErrorParseFloatError不是的原因是ParseIntError

并可能告诉我一个解决方案?

您说您正在尝试构建一个通用包装器std::<T>::from_str_radix,但您的示例使用了T::from_str_radixwhere T: Num,因此您正在尝试编写一个包装器Num::from_str_radix

一种选择是直接使用NumandFromStrRadixErr而不是创建包装器,最终Num就是包装器。

也许您想将包装器限制为原始整数并使用ParseIntError. 在这种情况下,您可以添加限制FromStrRadixErr = ParseIntError

fn foo<T>() -> Result<T, std::num::ParseIntError>
    where T: num_traits::Num<FromStrRadixErr = std::num::ParseIntError>,
{
    T::from_str_radix("4242", 10)
}
Run Code Online (Sandbox Code Playgroud)