简体   繁体   English

将泛型结构视为特征 object

[英]Treat generic struct as trait object

I have a struct with generic T for which I want to create a vector of instances of this struct, where for each instance T can be different.我有一个带有通用 T 的结构,我想为其创建一个包含该结构实例的向量,其中每个实例的 T 可以不同。 I realise I probably need to use a box and possibly need to treat my struct as a trait object, but I am not sure how, since it is not a collection of different structs which implement the same trait, but instead the same struct with a different generic.我意识到我可能需要使用一个盒子,并且可能需要将我的结构视为特征 object,但我不确定如何,因为它不是实现相同特征的不同结构的集合,而是具有相同结构的不同的泛型。 Below is what I have so far and hopefully illustrates what I am trying to achive, it doesn't work because the dyn keyword seems to expect a trait rather than a generic struct.下面是我到目前为止所拥有的,希望能说明我想要实现的目标,它不起作用,因为 dyn 关键字似乎期望一个特征而不是一个通用结构。

struct Point<T> {
    x: T,
    y: T,
}

struct Points {
    points: Vec<Box<dyn Point>>,
}
fn main() {
    let points = Points {
        points: vec![Point { x: 1, y: 2 }, Point { x: 1.1, y: 2.2 }],
    };
}

"The same struct with a different generic" behaves very similarly to "a different struct". “具有不同泛型的相同结构”的行为与“不同结构”非常相似。 Here, when dealing with trait objects, the concrete type doesn't matter, which is the key idea behind a trait object.在这里,在处理 trait 对象时,具体类型并不重要,这是 trait object 背后的关键思想。

For example:例如:

trait Trait {
  fn foo(&self) -> &'static str;
}

struct Point<T> {
  x: T,
  y: T,
}

// you may have different impls for different generics
impl<T> Trait for Point<T> {
  fn foo(&self) -> &'static str {
    "a point"
  }
}

fn main() {
  let points: Vec<Box<dyn Trait>> = vec![
    Box::new(Point {x: 1, y: 2}),
    Box::new(Point {x: 1.1, y: 2.2}),
    Box::new(Point {x: (), y: ()}),
  ];

  for point in points {
    println!("{}", point.foo());
  }
}

If you're already on nightly, and have the box_syntax feature enabled, you can also write box Point { x: 1, y: 2 } to save some boilerplate, although likely not worth switching to nightly for.如果您已经在 nightly 上,并且启用了box_syntax功能,您还可以编写box Point { x: 1, y: 2 }来节省一些样板文件,尽管可能不值得切换到 nightly 。

You can wrap the points in an enum :您可以将点包装在enum中:

struct Point<T> {
    x: T,
    y: T,
}

struct Points {
    points: Vec<PointType>,
}

enum PointType {
    U64(Point<u64>),
    F32(Point<f32>),
}

fn main() {
    let points = Points {
        points: vec![
            PointType::U64(Point { x: 1, y: 2 }),
            PointType::F32(Point { x: 1.1, y: 2.2 }),
        ],
    };
}

Playground 操场

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM