【问题标题】:Rust: How to restrict type parameters for derived traits [duplicate]Rust:如何限制派生特征的类型参数
【发布时间】:2020-06-19 22:29:46
【问题描述】:

我正在尝试编写一个通用函数,该函数采用指向 csv 文件的路径,将文件解析并反序列化为特定类型的记录向量并返回记录向量。

这是我的代码:

[dependencies]
csv = "1.1"
serde = { version = "1.0", features = ["derive"] }

首先是编译好的特定类型版本:

use csv;
use serde::Deserialize;
use std::path::Path;

#[derive(Debug, Deserialize)]
struct Person {
    name: String,
    fav_colour: String,
}

#[derive(Debug, Deserialize)]
struct Car {
    make: String,
    year: u8,
}

fn main() {}

fn parse_csv(file_path: &Path) -> Vec<Person> {
    // Create the csv reader
    let mut csv_reader = csv::Reader::from_path(file_path).unwrap();

    // Parse the csv and collect records
    let records: Vec<Person> = csv_reader
        .deserialize()
        .map(|record: Result<Person, csv::Error>| {
            record.expect(&format!("There was a problem parsing a line"))
        })
        .collect();

    // Return records
    records
}

parse_csv 函数适用于具体的Person 结构。

我怎样才能重新编写这个函数,使它接受派生反序列化的泛型类型/结构,例如它可以接受PersonCar

尝试失败:

fn parse_csv<T>(file_path: &Path) -> Vec<T> {
    // Create the csv reader
    let mut csv_reader = csv::Reader::from_path(file_path).unwrap();

    // Parse the csv and collect records
    let records: Vec<T> = csv_reader
        .deserialize()
        .map(|record: Result<T, csv::Error>| {
            record.expect(&format!("There was a problem parsing a line"))
        })
        .collect();

    // Return records
    records
}

产生:

error[E0277]: the trait bound `for<'de> T: _::_serde::Deserialize<'de>` is not satisfied
  --> src/main.rs:26:10
   |
26 |         .map(|record: Result<T, csv::Error>| {
   |          ^^^ the trait `for<'de> _::_serde::Deserialize<'de>` is not implemented for `T`
   |
help: consider restricting this type parameter with `T: for<'de> _::_serde::Deserialize<'de>`
  --> src/main.rs:19:14
   |
19 | fn parse_csv<T>(file_path: &Path) -> Vec<T> {
   |              ^
   = note: required because of the requirements on the impl of `_::_serde::de::DeserializeOwned` for `T`
   = note: required because of the requirements on the impl of `std::iter::Iterator` for `csv::reader::DeserializeRecordsIter<'_, std::fs::File, T>`

编译器提示:

help: consider restricting this type parameter with `T: for<'de> _::_serde::Deserialize<'de>`

我该怎么做呢? 我对 rust 比较陌生,在阅读了 traits and the where clause 上的 rust book 的信息(我怀疑答案在哪里)之后,我仍然无法编译。

【问题讨论】:

    标签: rust generic-programming serde


    【解决方案1】:

    您可以按照以下方式做一些事情:

    use serde::de::DeserializeOwned;
    
    fn parse_csv<T>(file_path: &Path) -> Vec<T>
    where
        T: DeserializeOwned,
    {
      /// deserialization logic
    }
    
    

    【讨论】:

    • 非常感谢。这行得通!我正在尝试where T: Deserialize,但没有运气。可能值得指出的是,在将 use serde::de::DeserializeOwned; 添加到原始问题中的导入后,可以使用 DeserializeOwned。非常感谢。
    • 是的。使用前需要导入。
    猜你喜欢
    • 1970-01-01
    • 2018-02-26
    • 1970-01-01
    • 2021-06-07
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 2020-08-17
    • 1970-01-01
    相关资源
    最近更新 更多