[英]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
本身。&T
對Getter
進行了全面實施。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.