gpt4 book ai didi

rust - 如何处理特征对象中的 Sized 要求?

转载 作者:行者123 更新时间:2023-12-03 11:38:42 24 4
gpt4 key购买 nike

我无法理解 Rust 中的特征和对象安全。

我有一个用于存储一些数据的 StoreTrait 和一个包含对 StoreTrait 的引用的 Resource 结构。

我希望Resource 有一个store 实例的引用,因为Resource 的很多方法都会使用store ,我不想将 store 显式传递给 Resource 上的每个方法。

我还需要让逻辑驻留在 trait 中,因为我有各种需要共享它的 impl(内存中和磁盘存储)。所以将它移到 impl 中不是我想要的。

Store 特征中,我尝试将 &Self 传递给一个函数,但它失败了,因为 &Self 不是 Sized:

pub trait StoreTrait {
fn create_resource(&self) {
let agent = Resource::new(self);
}
}

struct Resource<'a> {
store: &'a dyn StoreTrait,
}

impl<'a> Resource<'a> {
pub fn new(store: &dyn StoreTrait) -> Resource {
Resource { store }
}
}
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> src/lib.rs:3:35
|
3 | let agent = Resource::new(self);
| ^^^^ doesn't have a size known at compile-time
|
= note: required for the cast to the object type `dyn StoreTrait`
help: consider further restricting `Self`
|
2 | fn create_resource(&self) where Self: Sized {
| ^^^^^^^^^^^^^^^^^

这可能会成为 XY 问题

编译器建议在这些方法中使用 where Self: Sized 边界。但是,这会在稍后从 Resource 调用 save_resource() 时导致另一个问题,因为这意味着我正在调用具有 Sized< 的特征对象的方法 绑定(bind)。

pub trait StoreTrait {
// So after adding the trait bounds here...
fn create_resource(&self)
where
Self: Sized,
{
let agent = Resource::new(self);
}

// And here (internal logic requires that)...
fn save_resource(&self, resource: Resource)
where
Self: Sized,
{
// This now requires `Self: Sized`, too!
self.create_resource()
}
}

pub struct Resource<'a> {
pub store: &'a dyn StoreTrait,
}

impl<'a> Resource<'a> {
pub fn new(store: &dyn StoreTrait) -> Resource {
Resource { store }
}

pub fn save(&self) {
self.store.save_resource(self)
}
}

playground

error: the `save_resource` method cannot be invoked on a trait object
--> src/lib.rs:26:20
|
13 | Self: Sized;
| ----- this has a `Sized` requirement
...
26 | self.store.save_resource(self)
| ^^^^^^^^^^^^^

如何规避设置特征界限?或者如何防止在特征对象上调用方法?也许我正在做其他没有意义的事情?

编辑:我最终更改了函数的参数。每当我使用 &dyn StoreTrait 时,我都会切换到 &impl StoreTrait。这意味着为每个实现编译具有该签名的函数,这使得二进制文件更大一些,但它现在可以满足 sized 要求。耶!

最佳答案

也许如果您只是将函数从 trait 移动到每个实现,它就会做您想要的事情?

fn main() {}

pub trait StoreTrait {
fn create_resource(&self);

fn save_resource(&self, resource: &Resource);
}

struct Resource<'a> {
store: &'a dyn StoreTrait,
}

impl<'a> Resource<'a> {
pub fn new(store: &dyn StoreTrait) -> Resource {
Resource { store }
}

pub fn edit(&self) {
self.store.save_resource(self)
}
}

struct StoreMem {
resources: Vec<String>,
}

impl StoreTrait for StoreMem {
fn create_resource(&self) {
let agent = Resource::new(self);
}

fn save_resource(&self, resource: &Resource) {
//
}
}

struct StoreDisk {
resources: Vec<String>,
}

impl StoreTrait for StoreDisk {
fn create_resource(&self) {
let agent = Resource::new(self);
}

fn save_resource(&self, resource: &Resource) {
//
}
}

关于rust - 如何处理特征对象中的 Sized 要求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64975080/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com