预期的泛型类型,但找到具体类型(实现特征绑定)

时间:2017-09-08 00:41:17

标签: generics rust

我有两种方法可以做非常相似的事情,我想使用泛型和特征边界来重构。

以下是我的示例中的两种工作方法。

fn some_method_a(some_arg: u8) -> (Mode, Vec<A>)
{
    let mode = match some_arg {
        0 => Mode::ZERO,
        _ => Mode::NOTZERO,
    };

    let some_as = vec![A::new(0), A::new(1)];
    (mode, some_as)
}

fn some_method_b(some_arg: u8) -> (Mode, Vec<B>)
{
    let mode = match some_arg {
        0 => Mode::ZERO,
        _ => Mode::NOTZERO,
    };

    let some_bs = vec![B::new("Testing".to_string())];
    (mode, some_bs)
}

这是应该取代两者的方法。

fn some_method<T>(some_arg: u8) -> (Mode, Vec<T>)
where
    T: Filterable,
{
    let mode = match some_arg {
        0 => Mode::ZERO,
        _ => Mode::NOTZERO,
    };

    match &mode {
        &Mode::ZERO => (mode, vec![A::new(0), A::new(1)]),
        _ => (mode, vec![B::new("Testing".to_string())]),
    }
}

但是,我现在收到此错误,即使A(和B)实现了Filterable特征,我已将其指定为该方法的特征绑定。

error[E0308]: mismatched types
  --> src/main.rs:11:36
   |
11 |         &Mode::ZERO => (mode, vec![A::new(0), A::new(1)]),
   |                                    ^^^^^^^^^ expected type parameter, found struct `A`
   |
   = note: expected type `T`
              found type `A`

Permalink to playground 这是该计划的其余部分:

#[derive(Debug)]
enum Mode {
    ZERO,
    NOTZERO,
}

trait Filterable {
    fn get_some_data(&self) -> u8 {
        0
    }
}

struct A {
    some_data: u8,
}

struct B {
    some_other_data: String,
}

impl A {
    fn new(some_data: u8) -> A {
        A { some_data }
    }
}

impl B {
    fn new(some_other_data: String) -> B {
        B { some_other_data }
    }
}

impl Filterable for A {
    fn get_some_data(&self) -> u8 {
        self.some_data
    }
}

impl Filterable for B {}

some_method需要做什么才能返回模式元组和A或B结构的向量?

1 个答案:

答案 0 :(得分:1)

我对Rust泛型的理解是它们更像是C ++模板而不是你可能习惯的,因为它们在编译时是单态的并且是扩展的。

基本上是这样做的:

fn some_method<T>(some_arg: u8) -> (Mode, Vec<T>)
    where T: Filterable,

...是(如果编译成功)创建此方法的两个版本。期望返回(Mode, Vec<A>)的人和期望返回(Mode, Vec<B>)的人。当你以这种方式思考时,这根本没有意义。

你想要的是返回实现特征Filterable的东西的向量。因此,由于特征是未定义的,因此需要将它们包含在具有已知大小的某事中。 Box&#39}}可以解决这个问题:

fn some_method(some_arg: u8) -> (Mode, Vec<Box<Filterable>>)

这完全取消了泛型,只是返回一个盒装Filterable的矢量 - 实现实例。

当然,方法体现在也必须成为这个:

match &mode {
    &Mode::ZERO => (mode, vec![Box::new(A::new(0)), Box::new(A::new(1))]),
    _ => (mode, vec![Box::new(B::new("Testing".to_string()))]),
}

导致代码编译。

Here it is running on the Playground