簡體   English   中英

盒裝特征 object 仍然是未知大小

[英]Boxed trait object is still an unknown size

錯誤:

所以我收到以下錯誤:

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
        });
    }
}
  • 特性Sized沒有為dyn Getter實現
  • 特性Getter是為MapGetter<T, F>實現的

問題:

我不確定這個錯誤是什么意思或如何解決它。 dyn Getter的大小無法知道,但 MapGetter 的大小肯定可以,因為 MapGetter 是實現 Getter 特性的具體類型。 我不明白為什么我不能把它裝箱並退回。

我在這里遺漏了一些東西。 可以裝箱MapGetter ,我不能做的是將它提升為特征 object?

如果有助於在上下文中查看所有內容,這是我正在使用的完整示例:


筆記:

總的來說,我一直在嘗試通過動態調度來做到這一點。 部分是因為我想看看可以做什么,部分是因為我預見到自己想要一個dyn Operator的列表,其中下面的具體類型可能會有所不同。

我不想直接將運算符附加到Getter特征,因為最終我希望運算符代表可重用的邏輯片段,因此它們可以在事后(或不止一次)應用於Getter

完整上下文:

trait Getter {
    fn compute(&self) -> i32;

    fn pipe(&self, operator: &dyn Operator) -> Box<dyn Getter>
    where
        Self: Sized,
    {
        operator.apply(&self)
    }
}

impl<T: Getter> Getter for &T {
    fn compute(&self) -> i32 {
        (*self).compute()
    }
}

impl<T: Getter> Getter for Box<T> {
    fn compute(&self) -> i32 {
        (*self).compute()
    }
}

struct PureGetter<T>(T);

impl Getter for PureGetter<i32> {
    fn compute(&self) -> i32 {
        self.0
    }
}

struct MapGetter<T, F> {
    source: T,
        (*self).compute()
    f: F,
}

impl<T, F> Getter for MapGetter<T, F>
where
    T: Getter,
    F: FnMut(i32) -> i32 + Clone,
{
    fn compute(&self) -> i32 {
        (self.f.clone())(self.source.compute())
    }
}

trait Operator {
    fn apply<'a>(&self, a: &'a dyn Getter) -> Box<dyn Getter + 'a>;
}

struct PlusFive;

impl Operator for PlusFive {
    fn apply<'a>(&self, a: &'a dyn Getter) -> Box<dyn Getter + 'a> {
        Box::new(MapGetter {
            source: a,
            f: |n:i32| n + 5
        })
    }
}

fn main() {
    let result = PureGetter(0).pipe(&PlusFive).compute();
    println!("{:#?}", result);
}
error[E0277]: the size for values of type `dyn Getter` cannot be known at compilation time
  --> src/main.rs:71:9
   |
71 | /         Box::new(MapGetter {
72 | |             source: a,
73 | |             f: |n:i32| n + 5
74 | |         })
   | |__________^ doesn't have a size known at compile-time
   |
   = help: the trait `Sized` is not implemented for `dyn Getter`
   = help: the trait `Getter` is implemented for `MapGetter<T, F>`
note: required for `&dyn Getter` to implement `Getter`
  --> src/main.rs:24:17
   |
24 | impl<T: Getter> Getter for &T {
   |                 ^^^^^^     ^^
   = note: 1 redundant requirement hidden
   = note: required for `MapGetter<&dyn Getter, [closure@src/main.rs:73:16: 73:23]>` to implement `Getter`
   = note: required for the cast from `MapGetter<&dyn Getter, [closure@src/main.rs:73:16: 73:23]>` to the object type `dyn Getter`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `messin` due to previous error

此特定錯誤的最小化示例:

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);
}

操場

原因如下:

  • 要從Box<&dyn Getter>創建Box<dyn Getter> Getter> , &dyn Getter必須實現Getter本身。
  • &TGetter進行了全面實施。
  • 但是這個實現的通用參數有一個隱式的Sized界限,因此它不能應用於&dyn Getter

要解決眼前的問題,您可以簡單地放寬限制

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

在您的原始代碼中,推理是相似的,只是多了一個中間步驟-您必須將impl Getter傳遞給MapGetter ,這樣MapGetter就是Getter本身; 但傳入的值是&dyn Getter ,由於上述原因,它不是Getter


順便說一句,我會說同時擁有引用和Box es 是非常不合常理的。 如果您將自己限制在其中一個,您可能會有更簡單的方法——要么一直借用臨時引用,要么Box ing everything to own everything。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM