将A型向量转换为B型,其中A可转换为B



我正在学习rust,我想做的最基本的事情之一是取一个同质类型A的向量,它可以转换为另一个类型B(因为From<>已经实现,因此我们可以使用.into())。当我试着运行下面的代码时,我得到了以下结果:

struct A {
    x: String
}
struct B {
    x: String
}
impl From<A> for B {
    fn from(a: A) -> Self {
        B { x: a.x }
    }
}
impl B {
    pub fn from_many<T: Into<B> + Clone>(v: Vec<T>) -> Self {
        B { x: v.iter().map(|e| B::from(e.clone()).x).collect::<Vec<String>>().join(" ") }
    }
}
fn main() {
    ...
}

我:

error[E0277]: the trait bound `B: From<T>` is not satisfied
  --> src/main.rs:17:41
   |
17 |         B { x: v.iter().map(|e| B::from(e.clone()).x).collect::<Vec<String>>().join(" ") }
   |                                 ------- ^^^^^^^^^ the trait `From<T>` is not implemented for `B`
   |                                 |
   |                                 required by a bound introduced by this call
   |
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
   |
15 | impl B where B: From<T> {
   |        ++++++++++++++++

我最初尝试没有clone(),但认为它不接受引用:

...
impl B {
    pub fn from_many<T: Into<B>>(v: Vec<T>) -> Self {
        B { x: v.iter().map(|e| B::from(e).x).collect::<Vec<String>>().join(" ") }
    }
}
...

了:

error[E0277]: the trait bound `B: From<&T>` is not satisfied
  --> src/main.rs:17:41
   |
17 |         B { x: v.iter().map(|e| B::from(e).x).collect::<Vec<String>>().join(" ") }
   |                                 ------- ^ the trait `From<&T>` is not implemented for `B`
   |                                 |
   |                                 required by a bound introduced by this call
   |
   = help: the trait `From<A>` is implemented for `B`

我不是在这里要求任意的T,我要求的是T,它定义了Into<B> for T(在这种情况下,我相信它是定义的,因为我定义了From特征)。我做了什么蠢事吗?

你忽略了一个非常简单但容易忽略的事实:如果你有一个From<T> for U的实现,你就会自动有一个Into<U> for T的实现,但相反的是不正确的。因此,如果通过泛型需要T: Into<B>(这是正确的做法,因为它比B: From<T>更泛型),则需要使用.into()而不是B::from():

impl B {
    pub fn from_many<T: Into<B> + Clone>(v: Vec<T>) -> Self {
        B { x: v.iter().map(|e| e.clone().into().x).collect::<Vec<String>>().join(" ") }
    }
}

另一个,但不相关的,你错过的事情是,因为你有一个自有的Vec<T>,你可以使用into_iter(),然后你不需要.clone():

impl B {
    pub fn from_many<T: Into<B>>(v: Vec<T>) -> Self {
        B { x: v.into_iter().map(|e| e.into().x).collect::<Vec<String>>().join(" ") }
    }
}

最新更新