这是我上一个问题的后续问题:Rust: Read and map lines from stdin and handling different error types
我创建了以下结构和函数以从stdin中读取行并将其解析为整数,并且可以正常工作:
use std::io::BufRead;
use std::{io, num, str};
#[derive(Debug)]
enum InputError {
IOError(io::Error),
ParseIntError(num::ParseIntError),
}
impl From<io::Error> for InputError {
fn from(e: io::Error) -> InputError {
return InputError::IOError(e);
}
}
impl From<num::ParseIntError> for InputError {
fn from(e: num::ParseIntError) -> InputError {
return InputError::ParseIntError(e);
}
}
pub fn get_integer_lines<T>() -> Result<Vec<T>, InputError>
where
T: str::FromStr,
{
let stdin = io::stdin();
let my_values: Result<Vec<_>, InputError> = stdin
.lock()
.lines()
.map(|line| -> Result<T, InputError> { Ok(line?.parse::<T>()?) })
.collect();
my_values
}
现在,我想我将u32
替换为类型参数T,以允许使用任何类型的数字类型。为此,我假设我需要将T限制为实现FromStr特征的类型,然后以某种方式实现From特征以允许从FromStr :: Err转换为我的“ InputError”。
出现第一个错误
error[E0277]: `?` couldn't convert the error to `InputError`
--> src/lib.rs:30:69
|
30 | .map(|line| -> Result<T, InputError> { Ok(line?.parse::<T>()?) })
| ^ the trait `std::convert::From<<T as std::str::FromStr>::Err>` is not implemented for `InputError`
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= help: consider adding a `where InputError: std::convert::From<<T as std::str::FromStr>::Err>` bound
= note: required by `std::convert::From::from`
我尝试过这样的事情:
impl std::convert::From<<T as std::str::FromStr>::Err> for InputError {
fn from(e: <T as std::str::FromStr>::Err) -> InputError {
return InputError::ParseIntError(e)
}
}
但是结果是:
error[E0412]: cannot find type `T` in this scope
--> src/lib.rs:22:26
|
22 | impl std::convert::From<<T as std::str::FromStr>::Err> for InputError {
| ^ not found in this scope
所以基本上我想表达的是以下内容:
“我想为每个From<T::Err>
的{{1}}实现特征InputError
,同时也实现T
。这是否可能?如果可以,怎么办?
答案 0 :(得分:2)
所以基本上我想表达的是以下内容: “我想为每个
From<T::Err>
的{{1}}实现特征InputError
,同时也实现T
。这是否可能?如果可以,怎么办?
这不是错误的意思。
特征FromStr
具有关联的类型FromStr
。该错误表明该关联的错误类型无法转换为Err
。
首先,让我们简化一下类型参数:
InputError
这行得通!
与fn get_integer_lines() -> Result<Vec<u32>, InputError> {
let stdin = io::stdin();
let my_values = stdin
.lock()
.lines()
.map(|line| Ok(line?.parse()?))
.collect();
my_values
}
的{{1}}实现相关的Err
类型为u32
,您已经正确实现了FromStr
。
这不适用于ParseIntError
的原因是因为From<ParseIntError> for InputError
的{{1}}类型可以是任何东西。通过使用类型参数,您告诉编译器您希望该函数可用于任何可能的类型T
,但仅适用于可以转换T
的类型设置为您的FromStr::Err
类型。
错误消息给您提示:
T
让我们这样做:
FromStr::Err
这告诉编译器,您希望该函数对所有可能的InputError
有效,前提是{em>
= help: consider adding a `where InputError: std::convert::From<<T as std::str::FromStr>::Err>` bound
实现fn get_integer_lines<T>() -> Result<Vec<T>, InputError>
where
T: str::FromStr,
InputError: From<<T as str::FromStr>::Err>,
{
let stdin = io::stdin();
let my_values = stdin
.lock()
.lines()
.map(|line| Ok(line?.parse()?))
.collect();
my_values
}
,并且T
的{{1}}实现中关联的T
类型转换为FromStr