2 个稳定版本
1.1.0 | 2024 年 4 月 25 日 |
---|---|
1.0.0 | 2024 年 4 月 23 日 |
#3 in #内部
20KB
253 行
引入了一种类型,该类型将借用和所有值统一到一个内部借用的智能指针中,以保留所有权。
概览
此库提供了 CloneOnExtract
类型,它是一个可以持有借用值或所有值智能指针。这使得您可以创建一个接口,以便您的库可以处理借用值和所有值,通过将所有权的复杂性委托给简单的底层具体化。
缩写
- CloneOnExtract -
C
owT
oB
orrowed。这得益于与Cow
类似的功能,但与Cow
不同,并且具有不同的用例和功能,以更有用的方式扩展了Cow
的局限性。
结构
CloneOnExtract
类型是泛型,泛型为所有值和借用值,并且可以与任何遵循“借用和所有”继承结构的两个类型一起使用。
特质
CloneOnExtract
类型还实现了 Deref
、DerefMut
、Borrow
、BorrowMut
、AsRef
和 AsMut
特质,这使得将类型视为所有值时具有最大的灵活性。
此库还提供了三个特质,IntoCloneOnExtract
、IntoDerefCloneOnExtract
和 AsCloneOnExtract
,这些特质为符合 CloneOnExtract
类型要求的所有类型添加了方便的方法。这些类型是自动实现的,因此无需自行实现它们。
方法
CloneOnExtract
类型还提供了一些方便的方法来处理其持有的值,例如 as_owned
、as_borrowed
、is_owned
和 is_borrowed
。
示例
统一“按值”和“按引用”的特实现
use CloneOnExtract::{CloneOnExtract, AsCloneOnExtract, IntoCloneOnExtract};
pub trait AddTogether<T> {
fn add_together(self, other: T) -> i32;
}
impl AddTogether<u8> for u8 {
fn add_together(self, other: u8) -> i32 {
(self + other) as i32
}
}
impl AddTogether<&i32> for i32 {
fn add_together(self, other: &i32) -> i32 {
self + other
}
}
// The complication is seen in the following function, it is possible to bypass
// by cloning or implementing 2 different functions but this may not be possible
// in more complex situations that involve multiple levels of indirection.
// pub fn add_together_and_double<T: AddTogether<T / &T ???>>(lhs: T, rhs: ???)
// However, by using `CloneOnExtract`, this is possible with only a small runtime overhead
// that the compiler should optimize away if possible.
impl AddTogether<CloneOnExtract<'_, u8, u8>> for CloneOnExtract<'_, u8, u8> {
fn add_together(self, other: CloneOnExtract<u8, u8>) -> i32 {
self.into_owned().add_together(other.into_owned())
}
}
impl AddTogether<CloneOnExtract<'_, i32, i32>> for CloneOnExtract<'_, i32, i32> {
fn add_together(self, other: CloneOnExtract<i32, i32>) -> i32 {
self.into_owned().add_together(other.as_ref())
}
}
// Despite the complexity of the bounds for this function, in much more complex
// use cases it can dramatically decreases complexity and redundancy. The main
// point though, is that the function is extremely simple to call and can easily
// be composed in further functions using `CloneOnExtract` and is completely generic over
// value or reference arguments.
pub fn add_together_and_double<T: Clone>(lhs: CloneOnExtract<T, T>, rhs: CloneOnExtract<T, T>) -> i32
where
for<'a, 'b> CloneOnExtract<'a, T, T>: AddTogether<CloneOnExtract<'b, T, T>>,
{
lhs.as_borrowed().add_together(rhs.as_borrowed()) + lhs.as_borrowed().add_together(rhs)
}
// Note: CloneOnExtract() converts to an owned value but if we only had a reference we could
// use as_CloneOnExtract() insead. If our type implemented Deref then we also could use
// CloneOnExtract_deref() instead of cbt().
fn test() {
assert_eq!(add_together_and_double(1u8.CloneOnExtract(), 2u8.CloneOnExtract()), 6);
assert_eq!(add_together_and_double(1i32.CloneOnExtract(), 2i32.CloneOnExtract()), 6);
}