rust 装箱的特征对象仍为未知大小

tkclm6bt  于 2022-12-04  发布在  其他
关注(0)|答案(1)|浏览(114)

错误:

因此,我得到以下错误:
error[E0277]: the size for values of type 'dyn Getter' cannot be known at compilation time

struct PlusFive;

impl Operator for PlusFive {
    fn apply<'a>(&self, a: &'a dyn Getter) -> Box<dyn Getter + 'a> {
        Box::new(MapGetter {
            source: a, // A pointer to some Getter
            f: |n:i32| n + 5 // A way to later compute +5 on source
        });
    }
}
  • 没有为dyn Getter实现特性Sized
  • 特性Getter是针对MapGetter<T, F>实现的

问题:

我不知道这个错误意味着什么,也不知道如何解决它。dyn Getter的大小是不知道的,但是MapGetter的大小肯定是知道的!而且由于MapGetter是一个实现Getter特征的具体类型,我不明白为什么我不能将它装箱并返回它。
这里我遗漏了一些东西,我可以MapGetter装箱,但我不能把它提升到一个trait对象中?
下面是我正在使用的完整示例,如果它有助于在上下文中查看所有内容的话:

注:

总的来说,我一直在尝试用动态调度来实现这一点,部分原因是我想看看可以做些什么,部分原因是我预见到自己想要一个dyn Operator的列表,其中下面的具体类型可能会有所不同。
我不想将操作符直接附加到Getter特征,因为最终我希望操作符表示可重用的逻辑片段,这样它们就可以在事后(或多次)应用于Getter

完整上下文:

第一次

okxuctiv

okxuctiv1#

此特定错误的最小化示例:

trait Getter {}

impl<T: Getter> Getter for &T {}

impl Getter for () {}

fn main() {
    let getter: &dyn Getter = &();
    let getter: Box<dyn Getter> = Box::new(getter);
}

Playground
原因如下:

  • 若要从Box<&dyn Getter>建立Box<dyn Getter>&dyn Getter必须实作Getter本身。
  • &T具有针对Getter的一揽子实现。
  • 但是这个实作的泛型参数有隐含的Sized界限,因此无法套用至&dyn Getter

要解决当前的问题,只需relax the bound

impl<T: Getter + ?Sized> Getter for &T {}

在您的原始代码中,推理是类似的,只是多了一个中间步骤-您必须将impl Getter传递给MapGetter,这样MapGetter就是Getter本身;但传入的值是&dyn Getter,由于上述原因,它不是Getter
顺便说一句,同时使用reference和Box是非常不符合习惯的。如果你只使用其中一个,你可能会有一个更简单的方法--要么把临时引用一直借给你,要么Box ing一切来拥有一切。

相关问题