我正在写一个Vector类只是为了生锈,并认为能够为它实现Deref会很好,就像一个元组引用一样访问它。
例如,Vec2<f32>
可以取消引用为&(f32, f32)
。
我想出了这个:
pub struct Vec2<T> {
pub x: T,
pub y: T
}
impl<T> Deref for Vec2<T> {
type Target = (T, T);
fn deref(&self) -> &(T, T) {
&(self.x, self.y)
}
}
但是,由于编译器想要创建元组然后引用它,它会尝试
离开结构。
如果我使用type Target = (&T, &T)
然后返回&(&T, &T)
,我必须使用明确的生命周期说明符,因为我无法访问自我生命期,所以我不会这样做。
现在我的问题是:有没有办法在不复制值的情况下执行此操作?由于我经常使用小型,我可能不会真正使用Deref,但DerefMut可能会变得有用,我想象。
答案 0 :(得分:1)
现在,没有办法做到这一点!至少没有使用unsafe
。
考虑返回类型-> &Foo
。这意味着该函数返回对已存在于某处的Foo
的引用。特别是,如果您有fn deref(&self) -> &Foo
,则表示Foo
的生命至少与self
一样长,因为生命周期缩减会将其转换为fn deref<'a>(&'a self) -> &'a Foo
。
现在,(T, T)
就像Foo
一样。因此fn deref(&self) -> &(T, T)
表示您返回对已经存在于某处的T
元组的引用。但是没有这样的元组!你可以在函数中创建一个元组,但这不会长久存在。同样,如果您说-> &(&T, &T)
,则表示您返回对已存在于某处的元组(引用T
)的引用。但是又一次:你没有一个元组已经存在于某个地方。
因此,特征Deref
要求您返回对已经与self
中的内容完全相同的内容的引用。所以有了这个,就不可能做你想做的事。
您可以使用不安全的函数mem::transmute()
。毕竟,像你的结构和元组应该具有完全相同的内存布局,对吧?
是和否。两种内存布局可能都是相同的,但Rust并不能保证! Rust可以自由重新排序字段并添加填充字节。虽然我怀疑结构,元组结构和元组的内存布局完全相同,但我找不到源代码。因此,如果没有规范中的信息,转化在技术上是不安全的。
将来,HKT或更多通用关联类型可以解决这个问题。也就是说,它们不会直接解决您的问题,但是根据this RFC中定义的GAT,可以重新定义Deref
特征。那就是:
trait Deref {
type Target<'a>;
fn deref(&self) -> Self::Target<'a>;
}
现在我们被迫将生命“置于最外层”。有了这个,我们可以让实现Deref
的类型决定。在这种情况下,你可以写:
impl<T> Deref for Vec2<T> {
type Target<'a> = (&'a T, &'a T);
fn deref(&self) -> Self::Target {
(&self.x, &self.y)
}
}
这样,生命就在“内在”。
但GAT尚未实施,因此仍需要一些时间。此外,还不清楚标准库何时/如何/如何以向后不兼容的方式更改,以允许更改Deref
。