Deref struct to tuple 需要移动

Deref struct to tuple requires move

我正在编写一个 Vector class 只是为了在 Rust 中获得乐趣,并且认为能够为它实现 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) 然后 return a &(&T, &T) 我将不得不使用明确的生命周期说明符,我没有,因为我无法访问自我生命周期。

现在我的问题是:有没有一种方法可以在不复制值的情况下做到这一点?由于我经常使用小型类型,所以我可能不会真正使用 Deref,但我想 DerefMut 可能会变得有用。

总结

现在,没有办法做到这一点! 至少没有使用 unsafe


为什么?

考虑 return 类型 -> &Foo。这意味着函数 return 是对已经存在于某处的 Foo 的引用。特别是,如果您有 fn deref(&self) -> &Foo,则意味着 Foo 至少与 self 一样长,因为生命周期省略开始并将其转换为 fn deref<'a>(&'a self) -> &'a Foo

现在,(T, T)Foo 一样是一个类型。所以 fn deref(&self) -> &(T, T) 意味着你 return 对已经存在于某处的 T 的元组的引用。但是没有这样的元组!您可以在函数中创建一个元组,但这不会存在足够长的时间。类似地,如果你说 -> &(&T, &T) 你说你 return 对已经存在于某处的(对 T 的引用)的元组的引用。但同样:你没有一个元组已经存在于某个地方。

所以特征 Deref 要求你 return 引用已经与 self 中完全一样的东西。所以有了这个,就不可能做你想做的事。

不安全

您可以使用不安全函数 mem::transmute()。毕竟,像您这样的结构和元组应该具有完全相同的内存布局,对吧?

是也不是。两种内存布局可能是相同的,但 Rust 不保证! Rust 可以自由地重新排序字段和添加填充字节。虽然我怀疑结构、元组结构和元组的内存布局完全相同,但我找不到相关资料。因此,如果规范中没有该信息,转换在技术上是不安全的。

未来

将来,HKT 或更确切地说是泛型关联类型可以解决这个问题。也就是说,它们不会直接解决您的问题,但是使用 this RFC 中定义的 GAT,可以重新定义 Deref 特征。即:

trait Deref {
    type Target<'a>;
    fn deref(&self) -> Self::Target<'a>;
}

现在我们被迫放置生命周期 "at the outermost level"。有了这个,我们可以让实现 Deref 的类型来决定。在那种情况下你可以写:

impl<T> Deref for Vec2<T> {
    type Target<'a> = (&'a T, &'a T);

    fn deref(&self) -> Self::Target {
        (&self.x, &self.y)
    }
}

这样寿命是"on the inside".

但是GAT还没有实现,所以还需要一些时间。此外,尚不清楚 when/how/if 标准库是否以向后不兼容的方式更改,这将允许更改 Deref.