Rust 泛型:列出每个元素来自相同特征的位置?

问题描述 投票:0回答:1

我在 Rust 用户论坛上发现了这个问题:泛型:我可以说“每个元素都是 FromSql 的元组”。基本上,问题是知道如何做这样的事情:

trait Foo {}

struct A {}
impl Foo for A {}

struct B {}
impl Foo for B {}

fn main() {
    let x = (A{}, A{}, B{}, A{});
    bar(x);
}

fn bar<T: Foo>(tuple: (T...)) {

}

这段代码不起作用,这是一个想法。

那么,我们该怎么做呢?

templates generics rust tuples downcast
1个回答
0
投票
  • 第一步是创建一个 ToAny 特性,它将应用于我们所有的结构。
use std::any::Any;

pub trait ToAny {
    fn as_any(&self) -> &dyn Any;
}
  • 让我们创造我们的特质
trait Foo: ToAny {}

它需要实现 ToAny 特性来强制每个实现 Foo 的结构也实现 ToAny

  • 让我们创建我们的结构:
struct A {
    id: i32,
}

impl ToAny for A {
    fn as_any(&self) -> &dyn Any {
        self
    }
}

impl Foo for A {}

struct B {
    id: i32,
}

impl ToAny for B {
    fn as_any(&self) -> &dyn Any {
        self
    }
}

impl Foo for B {}

ToAny 的实现总是相同的,我们可以创建一个宏来轻松实现它。

  • 然后,我们可以创建一个 Vec 代替元组来存储我们的值:
let boxeds: Vec<Box<dyn A>> = vec![
    Box::new(A {id: 1}),
    Box::new(B {id: 2}),
    Box::new(A {id: 3}),
    Box::new(B {id: 4}),
];

// Stores the values being `B`.
let mut bees: Vec<&B> = vec![];

for boxed in &boxeds {
    // `Some(x)` if `boxed` contains a `B` value.
    let found = match boxed.as_any().downcast_ref::<B>() {
        Some(b) => b,
        None => {}, // it is a `A` value.
    };

    bees.push(found);
}

assert_eq!(bees, vec![
    &B {id: 2},
    &B {id: 4}
]);

如果我们参考问题,下面的代码:

fn bar<T: Foo>(tuple: (T...)) {

}

可以是这个有效代码:

fn bar(values: Vec<Box<dyn Foo>>) {

}

我已经写了一个要点文件正在为此进行测试。小心,我在这篇文章中更改了名称,FooA 并且只有 B 结构。

© www.soinside.com 2019 - 2024. All rights reserved.