gpt4 book ai didi

rust - 容器结构的Deref的实现

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

我有下一个代码,该代码实现了某种延迟/延迟的初始化,并且为了方便起见,我想使用内部可变性和Deref实现。

pub struct Deferred<T> {
value: RefCell<Value<T>>
}

pub enum Value<T> {
Initialized(T),
WaitingForValue
}

impl<T> Deferred<T> {
pub fn init_later() -> Self {
Self { value: RefCell::new(WaitingForValue) }
}
pub fn init(&self, value: T) {
self.value.replace(Initialized(value));
}
}

impl<T> Deref for Deferred<T> {
type Target = T;

fn deref(&self) -> &Self::Target {
if let Initialized(value) = self.value.borrow().deref() {
value
} else {
panic!("Deferred value must be initialized before the first usage")
}
}
}
但是我有一个错误:
error[E0515]: cannot return value referencing temporary value
|
30 | if let Initialized(value) = self.value.borrow().deref() {
| ------------------- temporary value created here
31 | value
| ^^^^^ returns a value referencing data owned by the current function
我尝试了不同的引用类型,但是无法正常工作。
另外,我试图用不安全的方法做到这一点:
fn deref(&self) -> &Self::Target {
unsafe {
if let Initialized(value) = &*self.value.as_ptr() {
&value
} else {
panic!("Deferred value must be initialized before the first usage")
}
}
}
在这种情况下它可以工作,但是我不确定这个不安全的代码不会产生未定义的行为。

最佳答案

您无法从RefCell返回共享引用,因为借阅检查是在运行时通过RefRefMut进行的,那些包装器实现了as_ref<Inner>,但是所产生的引用归包装器所有(Ref/RefMut),因此必须将其保留在瓢中。
这使得特质derefas_ref不易使用,但是例如,您可以通过在Deref而不是Value<T>上实现Deffered来获得相同的行为。

use std::{cell::{RefCell}, ops::{Deref}};

pub struct Deferred<T> {
value: RefCell<Value<T>>
}

pub enum Value<T> {
Initialized(T),
WaitingForValue
}

impl<T> Deferred<T> {
pub fn init_later() -> Self {
Self { value: RefCell::new(Value::WaitingForValue) }
}
pub fn init(&self, value: T) {
self.value.replace(Value::Initialized(value));
}
}

/// Implement deref on `Value` instead of `Deferred`
impl<T> Deref for Value<T> {
type Target = T;

fn deref(&self) -> &Self::Target {
if let Value::Initialized(value) = self {
value
} else {
panic!("Deferred value must be initialized before a first usage")
}
}
}

fn main() {
let val = Deferred::init_later();
val.init(String::from("Hello, world !"));
let _: &String = val.value.borrow().deref();
}

关于rust - 容器结构的Deref的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63449871/

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