假设有一个函数
fn basket_from_apple(apple: &'a mut Apple) -> Basket<'a>;这就形成了一个篮子,里面的某个地方是苹果。我不能修改basket_from_apple的代码。在另一个包裹里。
我想给basket_from_apple苹果,所以我不需要坚持它,我希望篮子的下降,以破坏苹果连同篮子。
有办法生锈吗?例如,是否有某种类似盒子的对象,AppleBasket,我可以在某种程度上把苹果和篮子放进去?我想保持苹果的隐私,我想保持篮子的不可移动,但仍然可以通过不可更改的参考。
发布于 2022-07-24 04:51:02
您可以使用AppleBasket库定义您的ouroboros,该库允许创建包含从其他部分借用的部件的“自引用结构”。如下所示:
#[ouroboros::self_referencing]
struct AppleBasket {
apple: Apple,
#[borrows(mut apple)]
#[covariant]
basket: Basket<'this>,
}
impl AppleBasket {
fn from_apple(a: Apple) -> AppleBasket {
AppleBasket::new(a, |a: &mut Apple| basket_from_apple(a))
}
}
// ...
fn some_func() {
let a = Apple::new();
let ab = AppleBasket::from_apple(a);
// `ab` can be freely moved
let b = ab.borrow_basket();
}有时候,这是解决你所描述的问题的最好的方法,也是唯一的方法。然而,ouroboros有一些性能成本、不稳定的风险(如果有任何bug),以及一个一定会有些尴尬的API,因此您应该将它视为最后的手段;通常有一种方法可以避免借用,并以不同的方式将类型组合在一起。
Basket,但是可以编写一个函数,在需要时创建它。有时候,
Basket,但确实有,最好的解决方案是修改库(如果欢迎的话,还可以贡献改进)。(例如,Basket可以保存实现AsMut<Apple>的泛型类型的值,也可以保存自定义的Fruit特征)。(但也可能有显而易见的或微妙的原因,为什么库的类型必须按照它们的方式工作。)。
Apple和Basket放在运行在线程或async任务上的循环中的局部变量中,后者接受指示它如何操作Basket的消息。消息通道(可能是合适的包装器类型)可以自由地传递。Apple (或一个有限的数字),那么您可以对它进行Box::leak()以获得一个&'static mut Apple,从而允许您创建一个Basket<'static>。这样做的缺点是不可能(安全地)恢复Apple所使用的内存,因此如果苹果定期被创建和销毁,就不应该这样做。https://stackoverflow.com/questions/73095398
复制相似问题