代码之家  ›  专栏  ›  技术社区  ›  Todd

Traits,通过返回`Self::Item的trait方法返回对所属字段的引用`

  •  0
  • Todd  · 技术社区  · 5 年前

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

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

    我想以类似的方式从trait方法返回对owned字段的引用。假设 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;
       |              ^^^^   ^^^
    

    我已经尝试了上述建议,甚至宣布 'a 在…上 Charlie 的结构并添加 PhantomData 并在我的其他消息来源中彻底添加 一 s.编译器在整个过程中不断地抱怨、抱怨和唠叨。

    我设法找到了 this post on StackOverflow ,但那里的解决方案似乎都需要修改特性。

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

    这个 阿尔法 我一直在努力的特质方法实际上是

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

    我试图返回另一个包装的迭代器类型,其中 I 是包装迭代器。这个 Iterator 特质本身并不能定义我可以利用的任何一生。

    我知道有一种方法可以绕过这个限制,使用智能指针类来封装我想要共享的字段 查理 。那就让它成为我的 Item 类型我只是希望有一些开销更少的东西。

    1 回复  |  直到 5 年前
        1
  •  1
  •   Silvio Mayolo    5 年前

    不幸的是,这种特质的合同不允许这样做。

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

    这说明,如果 Self 是一个 Alpha ,那么“存在一些单一的 Self::Item 我可以从中获得 任何 &mut self 具有 任何 “.你想要”存在一个类 自身::项目 其寿命与 &mut self 以一种不平凡的方式”。

    解决这个问题最简单的方法是 bravo 拿 self 按价值计算。

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

    现在,合同上写着“有办法获得 自身::项目 来自 自己 ”,这要简单得多。我们可以将其实现为

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