首页 > 解决方案 > Traits,通过返回 `Self::Item` 的 trait 方法返回对拥有字段的引用

问题描述

在其他情况下允许返回对拥有字段的引用。例如,下面的代码编译得很好。

struct Charlie<T> {
    delta: T,
}

impl<T> Charlie<T> {
    fn delta(&self) -> &T
    {
        &self.delta
    }
}

我想以类似的方式从 trait 方法返回对拥有字段的引用。假设这Alpha是标准库中的一个特征,所以我不能修改它。

有没有办法实现这个?

trait Alpha {
    type Item;
    fn bravo(&mut self) -> Self::Item;
}

impl<T> Alpha for Charlie<T> {
    type Item = &T;
    
    fn bravo(&mut self) -> Self::Item
    {
        &self.delta
    }
}

以上内容无法编译,并且错误消息似乎不适用。如果我尝试遵循错误消息建议,事情就会变得复杂,并且我会遇到一系列错误,并且建议也不会成功。

   Compiling playground v0.0.1 (/playground)
error[E0106]: missing lifetime specifier
  --> src/main.rs:22:17
   |
22 |     type Item = &T;
   |                 ^ expected named lifetime parameter
   |
help: consider introducing a named lifetime parameter
   |
22 |     type Item<'a> = &'a T;
   |              ^^^^   ^^^

我已经尝试了上述建议,甚至'aCharliestruct 上声明并添加了一个PhantomData字段,并用 s 彻底填充了我的其余来源'a。编译器在整个过程中不断地抱怨、抱怨和唠叨。

我设法在 StackOverflow 上找到了这篇文章,但那里的解决方案似乎都需要修改特征。

我在想我想做的事情可能是不可能的。但我真的不明白为什么不。

我一直在努力的Alpha特质方法实际上是

    type Item = Take<&I>;
    fn next(&mut self) -> Option<Self::Item> { ... }

我试图返回另一个包装的迭代器类型,I包装的迭代器在哪里。Iterator特质本身并没有定义我可以利用的任何生命周期。

我确实知道一种解决此限制的方法,使用智能指针类来封装我想要共享的字段Charlie。然后让它成为我的Item类型。我只是希望开销更少的东西。

标签: rust

解决方案


不幸的是,该特征的合同不允许这样做。

trait Alpha {
  type Item;
  fn bravo(&mut self) -> Self::Item;
}

这就是说,如果Self是一个Alpha,那么“存在一些Self::Item我可以从任何 一生&mut self中得到的单曲”。你想要“存在一个类,Self::Item其生命周期以&mut self非平凡的方式相关”。

解决这个问题的最简单方法是按价值bravo取值self

trait Alpha {
  type Item;
  fn bravo(self) -> Self::Item;
}

现在,合同说“有一些方法可以Self::Item从 a 中获取 a self”,这要简单得多。我们可以将其实现为

impl<'a, T> Alpha for Charlie<&'a mut T> {
  type Item = &'a T;
    
  fn bravo(self) -> Self::Item {
    &self.delta
  }
}

推荐阅读