英文:
How do I have a trait as a owned field of a struct?
问题
抱歉,你的请求是要将英文文本翻译成代码部分,请看下面的翻译:
我对Rust还比较新,我试图实现一个结构体,该结构体可以拥有不同的实现了共同特性的结构体作为字段。
在传统的带有垃圾收集器的编程语言中,我会像这样实现它:
```rust
pub struct MemoryMapper {
regions: Vec<Region>,
}
trait MemoryMappable: Sized {
}
pub struct Region {
device: dyn MemoryMappable,
start: u32,
end: u32,
remap: bool
}
但是在这里,我遇到了以下编译错误:
无法在编译时知道类型`(dyn MemoryMappable + 'static)`的大小
未实现`(dyn MemoryMappable + 'static)`的`Sized`特性
结构体中只能有最后一个字段具有动态大小类型
将字段的类型更改为具有静态已知大小
我尝试将Sized
作为MemoryMappable
的超特性,但仍然在以下代码中出现问题:
pub fn map(&mut self, device: dyn MemoryMappable, start: u32, end: u32, remap: bool) -> &Region {
self.regions.insert(0, Region{device, start, end, remap});
return self.regions.get(0).unwrap();
}
无法将`MemoryMappable`特性转换为对象
`MemoryMappable`无法转换为对象
因为根据Rust文档中的对象安全性:
Sized
不能是超特性。换句话说,它不能要求Self: Sized
。
我不知道该如何处理这个问题。
英文:
I'm fairly new to Rust, I was tying to implement a struct that could have different structs that implemented a common trait as a field
In traditional programming languages with garbage collector I would have implemented it like this:
pub struct MemoryMapper {
regions: Vec<Region>,
}
trait MemoryMappable: Sized {
}
pub struct Region {
device: dyn MemoryMappable,
start: u32,
end: u32,
remap: bool
}
But here I have the following compilation error:
the size for values of type `(dyn MemoryMappable + 'static)` cannot be known at compilation time
the trait `Sized` is not implemented for `(dyn MemoryMappable + 'static)`
only the last field of a struct may have a dynamically sized type
change the field's type to have a statically known size
I have tried making Sized a supertrait of MemoryMappable, but it still gives me issues with the following code:
pub fn map(&mut self, device: dyn MemoryMappable, start: u32, end: u32, remap: bool) -> &Region {
self.regions.insert(0, Region{device, start, end, remap});
return self.regions.get(0).unwrap();
}
the trait `MemoryMappable` cannot be made into an object
`MemoryMappable` cannot be made into an object
Because from Rust documentation about object safety
> Sized must not be a supertrait. In other words, it must not require Self: Sized.
I have no idea of how to go about this at this point
答案1
得分: 3
Sized
结构体的字段可以存在于堆栈上,因此在编译时必须具有已知大小。这就是 Sized
错误在说什么。
dyn Trait
是 "实现 Trait
的任何类型"。那它的大小是多少呢?嗯,这取决于底层类型是什么。
因此,即使 Trait
作为超trait 具有 Sized
(这只是保证实现 Trait
的任何类型也实现 Sized
,但你仍然不知道它是哪个),dyn Trait
从不实现 Sized
。
实际上,将 Sized
作为 Trait
的超trait 是用来选择不实现对象安全性的方式,这使得构造 dyn Trait
变得不可能。
相反,绕过这个问题的方式是使用类似指针的类型:
Box<dyn Trait>
创建一个拥有的指针&dyn Trait
创建一个引用Arc<dyn Trait>
创建一个引用计数的指针- 等等。
指针类型的选择取决于您的用例,但在大多数情况下,Box<dyn Trait>
是可以的,也是一个很好的起点。
英文:
Fields of Sized
structs can exist on the stack, and so must have a known size at compile time. This is what the Sized
error is saying.
dyn Trait
is "any type that implements Trait
. So what is its size? Well, it depends on what the underlying type is.
Therefore, dyn Trait
never implements Sized
, even if Trait
has Sized
as a supertrait (all this does is guarantee that any type that implements Trait
also implements Sized
, but you still don't know which one it is).
In fact, making Sized
a supertrait of Trait
is how you opt-out of object safety, which makes it impossible to construct a dyn Trait
.
Instead, the way you get around this is by using a pointer-like type:
Box<dyn Trait>
creates an owned pointer&dyn Trait
creates a referenceArc<dyn Trait>
creates a reference counted pointer- etc.
The choice of pointer type depends on your use case, but in most scenarios, Box<dyn Trait>
is fine, and is a good starting point.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论