首页 文章

Deref struct to tuple需要移动

提问于
浏览
1

我正在写一个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 回答

  • 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 特征 . 那是:

    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)
        }
    }
    

    这样,生命周期就“在内部” .

    但GAT尚未实施,因此仍需要一些时间 . 此外,还不清楚何时/如何/如何/以及如何以向后不兼容的方式更改标准库,这将允许更改 Deref .

相关问题