我正在写一个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可能会变得有用,我想 .
1 回答
摘要
现在, there is no way to do that! 至少没有使用
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或更多的通用关联类型可以解决这个问题 . 也就是说,它们不会直接解决您的问题,但是使用GAT,如this RFC中所定义的,可以重新定义
Deref
特征 . 那是:现在我们被迫把生命"at the outermost level" . 有了这个,我们可以让实现
Deref
的类型决定 . 在这种情况下,你可以写:这样,生命周期就“在内部” .
但GAT尚未实施,因此仍需要一些时间 . 此外,还不清楚何时/如何/如何/以及如何以向后不兼容的方式更改标准库,这将允许更改
Deref
.