Rust中是否有通用模式定义可持有或借用值的结构体?
Rust中通用结构体:同时支持持有值与借用值的方案探讨
本文探讨Rust编程中的一类通用问题:如何定义结构体,使其无需关心自身是持有还是借用某一值。
假设我们有结构体Foo,它需要访问&Bar来完成功能,初始定义如下:
struct Foo<'a> { bar: &'a Bar, } impl Foo<'_> { fn fulfill_purpose(&self) { let bar = self.bar; // 我们获得了&Bar的访问权 \o/ } }
但在不同场景下,获取Bar的方式不同,初始定义会遇到各种局限:
- 若已在栈上持有
Bar,可直接构造Foo,此时Foo的生命周期与bar一致:let bar = construct_bar(); let foo = Foo { bar: &bar }; // 此时Foo的生命周期与bar一致 \o/ - 若从磁盘/网络等获取
Bar并封装为工具函数返回Foo,当前定义会因生命周期问题无法返回:fn fetch_foo() -> Foo { let bar = fetch_bar(); let foo = Foo { bar }; // 错误!bar仅存在于函数作用域,无法返回foo } - 若将
Foo改为持有Bar,则在共享Bar或使用全局Mutex包裹的Bar时又会遇到生命周期问题:static GLOBAL_BAR: Mutex<Bar>; fn global_foo() -> Foo { let bar = GLOBAL_BAR.lock(); let foo = Foo { bar: &bar }; // 错误!MutexGuard仅存在于函数作用域,无法返回foo }
为此尝试泛型方案,通过抽象一个能提供&Bar的类型参数来解决:
struct Foo<SomeBar> { bar: SomeBar, } impl<SomeBar: SomeTrait> Foo<SomeBar> { fn fulfill_purpose(&self) { // 假设SomeBar::as_bar(&self) -> &Bar let bar = self.bar.as_bar(); // 我们获得了&Bar的访问权 \o/ } }
但标准库中的现有 trait 存在不足:
Deref和AsRef无针对T的 blanket 实现,无法直接支持Foo持有Bar的场景;Borrow虽有 blanket 实现,但部分标准库类型(如std::cell::Ref)未实现该 trait,通用性不足。
本人尝试通过定义新类型Owned<T>配合Deref实现:
struct Owned<T>(T); impl<T> Deref for Owned<T> { type Target = T; fn deref(&self) -> &Self::Target { &self.0 } } struct Foo<SomeBar: Deref<Target=Bar>> { bar: SomeBar, }
但该方案未在实际代码中见过,故询问:是否存在此类问题的通用解决方案?本人的思路是否存在根本性错误?
注:此问题与使用Cow运行时追踪所有权的方案不同,需通过泛型静态追踪所有权。
内容的提问来源于stack exchange,提问作者Kritzefitz
相关产品推荐
相关产品推荐

