我怎样才能对包含不同类型的链表进行静态分派,这些类型都实现了一个特征?

How can I have static dispatch for a linked list containing different types all implementing a trait?

我有这个工作代码:

struct Layer<'a> {
    parent: Option<Box<Layer<'a>>>,
    value: Box<dyn Renderable + 'a>,
}

我想要一个使用静态分派的版本:

struct Layer<'a, R: Renderable> {
    parent: Option<&'a Layer<'a, /* ? */>>,
    value: R,
}

替换问号的类型实现了Renderable,但不一定是R,比如可以是T: Renderable。我想避免使用 dyn Renderable 的任何解决方案,以保持静态调度。

类型 T: RenderableLayer 实例化时已知,不会更改。

TL;DR:不可能(至少w/o variadic generics*)

  • 现在 Layer 结构需要 2 个通用参数:R'a.

  • 假设我们找到了 /* ? */ 的正确类型。我们将其命名为 T0.

  • 那么 Layer 结构将需要 3 通用参数:T0R'a.

  • 然后您必须为 parent 字段提供一个通用参数。我们将其命名为 T1.

  • 那么 Layer 结构将需要 4 个通用参数:T1T0R'a .

  • 然后您必须为 parent 字段提供一个通用参数。我们将其命名为 T2.

  • <...>

  • 然后 Layer 结构将需要 i+2 通用参数:TiTi-1、... T1T0R'a.
  • 然后您必须为 parent 字段提供一个通用参数。我们将其命名为 Ti+1.
  • 然后 Layer 结构将需要 i+1+2 通用参数:Ti+1TiTi-1、... T1T0R'a.
  • <...>

最后,你有无限递归。 parent 字段的附加通用参数必须定义为 Layer 结构的一部分。这导致为 Layer 引入了一个新的通用参数。这会为 parent 字段引入额外的通用参数。

为了分解递归,parent 的附加通用参数不应成为 Layer 定义的一部分。如果参数不是 Layer 定义的一部分,那么我们无法在编译时计算 Layer 大小。可能的解决方式是&dynBox.

*另一种可能的解决方案是 variadic generics,但看起来我们至少在接下来的几个月甚至几年内不会有它。