【问题标题】:Require type parameter to be a struct要求类型参数是结构
【发布时间】:2020-01-08 04:49:21
【问题描述】:

我有一个函数,我指定了一个类型参数T on,我假设它是一个结构。然后我将 T 的迭代器收集到 Vec 中:

pub fn get_matches<T>(
    &self,
) -> Vec< T> 
{
    ...
    some_iter.
        .map(|(k, _v)| T{key:(**k).to_string(), hits: 0})
        .collect()
}

我收到this error

96 |             .map(|(k, _v)| T{key:(**k).to_string(), hits: 0})
   |                            ^ not a struct, variant or union type

我尝试将返回类型作为类型参数,但我不知道如何获取Vec 的元素类型并对其进行实例化。我只想生成特定形状的元素(即带有key: stringhits: usize)并返回调用者期望的容器。

【问题讨论】:

  • 您接受任何类型的T。您如何确定T 将具有以下字段(并且只有这些字段):keyhits
  • 这就是我要指定的内容。或者,我很高兴拥有 -> T,并执行T::ElemType{key: , hits :} 之类的操作,但我也不知道如何指定它。 (我希望那时我必须对 T::ElemType 施加约束)。

标签: rust


【解决方案1】:

Rust 泛型不同于 C++ 模板。它们不同是有正当理由的,例如更好的错误报告和更快的编译。

在 C++ 中,模板(如果我们过度简化的话)类型在初始调用阶段不会被检查,而是模板会继续扩展,直到它成功,或者遇到该特定类型不支持的操作。

在 Rust 中,类型会立即检查。规范必须预先给出,这意味着在调用站点捕获任何错误,而不是在模板扩展的深处。

您的具体示例假设每个T 都应该有字段keyhits,但T 可以是从原始类型到没有key 或@987654329 的非公共结构的任何东西@字段。

Rust 的做事方式是声明一个 trait 并使用它来指定该类型具有特定的构造函数。在这种情况下,由于静态多态性,特征将是零成本抽象。

trait StringConstructable {
    fn new(string: String) -> Self;
}

struct Test {
    key: String,
    hits: usize
}

impl StringConstructable for Test {
    fn new(string: String) -> Self {
        Test {
            key: string,
            hits: 0
        }
    }
}

fn test<T: StringConstructable>() -> T {
    T::new("test".to_string())
}

Playground link

或者为您的T 实施并要求From&lt;String&gt;

struct Test {
    key: String,
    hits: usize
}

impl From<String> for Test {
    fn from(string: String) -> Test {
        Test {
            key: string,
            hits: 0
        }
    }
}

fn test<T: From<String>>() -> T {
    T::from("test".to_string())
}

Playground link

【讨论】:

  • Rust Book 中的Bounds chapter使用泛型时,类型参数通常必须使用特征作为边界来规定类型实现的功能。好答案。您可以解释 Rust 预先检查“规范”的方式是通过使用特征边界
猜你喜欢
  • 1970-01-01
  • 2012-05-30
  • 1970-01-01
  • 2020-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-13
  • 2021-02-27
相关资源
最近更新 更多