能否在稳定版Rust中为MaybeOwned trait实现全ToOwned泛化?
基于ToOwned泛型实现MaybeOwned trait
我定义了如下trait,用于统一处理自有值和借用值:
/// 用于接受自有或借用值的trait trait MaybeOwned<B: ToOwned + ?Sized> { fn is_owned(&self) -> bool; fn into_owned(self) -> <B as ToOwned>::Owned; fn borrow(&self) -> &B; }
期望行为示例
我希望这个trait能支持以下使用场景:
fn mo_u32<T: MaybeOwned<u32>>(x: T) { println!("{} {}", x.is_owned(), x.borrow()); } fn mo_str<T: MaybeOwned<str>>(x: T) { println!("{} {}", x.is_owned(), x.borrow()); } fn main() { mo_u32(42); // 输出 true 42 mo_u32(&42); // 输出 false 42 mo_str("test"); // 输出 false test mo_str("test".to_string()); // 输出 true test mo_str(&"test".to_string()); // 输出 false test }
设计背景
这个trait的核心作用是让函数能同时兼容自有值和借用值,避免代码库中针对大型数据容器的不必要克隆操作。虽然用Cow也能实现类似效果,但Cow会把克隆决策推迟到运行时(取决于内联优化情况),还会增加调用者的代码冗余。
现有实现的局限
我已经写出了一个可用的实现,但它不是完全基于ToOwned的泛型实现——比如要让MaybeOwned<str>支持String类型,必须单独编写实现。以下是当前的实现代码,包含了String<->str、Vec<T><->[T]以及Cow的适配(注:原代码中Cow的is_owned逻辑写反,已修正):
impl<T: ToOwned<Owned=T>> MaybeOwned<T> for T { fn is_owned(&self) -> bool { true } fn into_owned(self) -> T { self } fn borrow(&self) -> &T { self } } impl<B: ToOwned + ?Sized> MaybeOwned<B> for &B { fn is_owned(&self) -> bool { false } fn into_owned(self) -> <B as ToOwned>::Owned { self.to_owned() } fn borrow(&self) -> &B { self } } impl<B: ToOwned + ?Sized> MaybeOwned<B> for Cow<'_, B> { fn is_owned(&self) -> bool { match *self { Cow::Borrowed(_) => false, // 原代码逻辑颠倒,已修正:借用状态返回false Cow::Owned(_) => true, // 自有状态返回true } } fn into_owned(self) -> <B as ToOwned>::Owned { Cow::into_owned(self) } fn borrow(&self) -> &B { Borrow::borrow(self) } } // 必须单独编写的非泛型实现 impl MaybeOwned<str> for String { fn is_owned(&self) -> bool { true } fn into_owned(self) -> String { self } fn borrow(&self) -> &str { self } } impl MaybeOwned<str> for &String { fn is_owned(&self) -> bool { false } fn into_owned(self) -> String { self.clone() } fn borrow(&self) -> &str { self } } impl<T: Clone> MaybeOwned<[T]> for Vec<T> { fn is_owned(&self) -> bool { true } fn into_owned(self) -> Vec<T> { self } fn borrow(&self) -> &[T] { self } } impl<T: Clone> MaybeOwned<[T]> for &Vec<T> { fn is_owned(&self) -> bool { false } fn into_owned(self) -> Vec<T> { self.clone() } fn borrow(&self) -> &[T] { self } }
问题
能否在稳定版Rust中,完全基于ToOwned trait写出泛型实现,不需要为String、Vec<T>等类型单独编写MaybeOwned的实现?
内容的提问来源于stack exchange,提问作者orlp
相关产品推荐
相关产品推荐

