Rust:为关联类型实现特征 "From"(错误)

标签 rust traits

这是我之前问题的后续问题: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> 实现特征 InputError 为每个 T 也实现 FromStr 。这甚至可能吗?如果可以,怎么做?

最佳答案

So basically what I want to express is something along the lines of: "I want to implement the trait From<T::Err> for my InputError for every T which also implements FromStr. Is this even possible and if so, how?

这不是错误的意思。

性状 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
}

这行得通!

关联的Err输入 u32FromStr实现是 ParseIntError并且您已正确实现 From<ParseIntError> for InputError .

这对 T 不起作用的原因是因为TFromStr::Err类型可以是任何东西。通过使用类型参数,您告诉编译器您希望此函数适用于任何可能类型 T , 但它只适用于 FromStr::Err 的类型可以转换成你的InputError类型。

错误信息给了你一个提示:

= 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 前提是:

  • T工具 FromStr并且,
  • 相关的ErrT 输入的 FromStr实现可以转换为 InputError

关于Rust:为关联类型实现特征 "From"(错误),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59214210/

相关文章:

rust - 在Rust教程代码中获取 “error[E0599]: no method named write_fmt found”错误

c++ - Rust Cargo CMake 与 C++ 库依赖项集成

rust - 如何将哈希转换为字符串? [复制]

generics - Rust:从(仅)<T> 不同的函数返回通用结构

module - 看不懂 Rust 模块系统

rust - 如何通过具有语法扩展的特征标识符获取原始 AST?

rust clone() vs Rc 还是 Arc?

testing - 如何运行主二进制文件,然后在 Rust 中运行基于它的测试?

parsing - 如何使用 nom 将带符号的字符串解析为 i32?

generics - 为什么在具有泛型类型参数的结构定义中使用特征边界?