Rust - 在内存布局和更简单的泛型的枚举中包装特征?

Rust - wrapping trait in an enum for memory layout and simpler generics?

所以我的代码中有如下内容:

// Trait
trait Shape {
    fn area(&self) -> f32;
}

// Rect
struct Rect {
    width: f32,
    height: f32
}
impl Shape for Rect {
    fn area(&self) -> f32 {
        self.width * self.height
    }
}

// Circle
struct Circle {
    radius: f32
}
impl Shape for Circle {
    fn area(&self) -> f32 {
        self.radius * self.radius * std::f32::consts::PI
    }
}

// usage
fn use_shapes(shapes: Vec<Box<dyn Shape>>) {
    // ...
}

而且我真的不喜欢 Box<dyn ...>,无论是性能还是感觉很恶心。我对我的特质的实现很少而且很明确,所以我觉得成为枚举是一个很好的候选人。

在将其转换为枚举的过程中,我偶然发现了以下模式:

// Wrapper enum
enum ShapeEnum {
    Rect(Rect),
    Circle(Circle)
}
impl Shape for ShapeEnum {
    fn area(&self) -> f32 {
        match self {
            ShapeEnum::Rect(data) => data.area(),
            ShapeEnum::Circle(data) => data.area(),
        }
    }
}

// new usage
fn use_shapes(shapes: Vec<ShapeEnum>) {
    // ...
}

非常整洁。它也感觉像是在某种程度上作弊。它按预期编译和工作,它非常不寻常,我想看看是否有任何我现在没有看到的意外 drawbacks/costs/quirks?

我还想知道,由于枚举实现的确定性,它是否会成为一个好的宏?自动围绕特征及其一组实现器生成枚举,它本身实现了特征,就像 dyn 版本一样。

I wanted to see if there are any unexpected drawbacks/costs/quirks that I'm not seeing right now?

我能想到的唯一真正的缺点是你最终集中了所有这些类型的定义——这使得第三方更难挂钩到你的代码中。

您可以通过添加动态分派枚举来解决这个问题,这意味着您只会在那些外部定义的类型上获得较慢的行为。

// Wrapper enum
enum ShapeEnum {
    Rect(Rect),
    Circle(Circle),
    Dynamic(Box<T: Shape>),
}

impl Shape for ShapeEnum {
    fn area(&self) -> f32 {
        match self {
            ShapeEnum::Rect(data) => data.area(),
            ShapeEnum::Circle(data) => data.area(),
            ShapeEnum::Dynamic::(data) => data.area(),
        }
    }
}

I'm also wondering if, because of the deterministic nature of the enum implementation, it would make a good macro? Automatically generating an enum around a trait and a set of its implementors, which itself implements the trait just like a dyn version would

看起来 enum_dispatch 板条箱几乎完全可以做到这一点。

免责声明:我自己没用过。