#智能指针 #借用 #所有 #所有权 # #保留 #内部

ctb

ctb 将借用和所有值统一成一个内部借用的智能指针以保留所有权

2 个稳定版本

1.1.0 2024 年 4 月 25 日
1.0.0 2024 年 4 月 23 日

#3 in #内部

MIT/Apache

20KB
253

引入了一种类型,该类型将借用和所有值统一到一个内部借用的智能指针中,以保留所有权。

概览

此库提供了 CloneOnExtract 类型,它是一个可以持有借用值或所有值智能指针。这使得您可以创建一个接口,以便您的库可以处理借用值和所有值,通过将所有权的复杂性委托给简单的底层具体化。

缩写

  • CloneOnExtract - Cow To Borrowed。这得益于与 Cow 类似的功能,但与 Cow 不同,并且具有不同的用例和功能,以更有用的方式扩展了 Cow 的局限性。

结构

CloneOnExtract 类型是泛型,泛型为所有值和借用值,并且可以与任何遵循“借用和所有”继承结构的两个类型一起使用。

特质

CloneOnExtract 类型还实现了 DerefDerefMutBorrowBorrowMutAsRefAsMut 特质,这使得将类型视为所有值时具有最大的灵活性。

此库还提供了三个特质,IntoCloneOnExtractIntoDerefCloneOnExtractAsCloneOnExtract,这些特质为符合 CloneOnExtract 类型要求的所有类型添加了方便的方法。这些类型是自动实现的,因此无需自行实现它们。

方法

CloneOnExtract 类型还提供了一些方便的方法来处理其持有的值,例如 as_ownedas_borrowedis_ownedis_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);
}

无运行时依赖