在“get_trait_mut”中返回对trait的可变引用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在“get_trait_mut”中返回对trait的可变引用相关的知识,希望对你有一定的参考价值。

考虑以下:

pub trait Inner {}

pub struct Thing<'a> {
    inner: &'a Inner,
}

impl<'a> Thing<'a> {
    pub fn get_inner(&self) -> &Inner {
        self.inner
    }

    pub fn get_inner_mut(&mut self) -> &mut Inner {
        &mut self.inner
    }
}

导致:

error[E0277]: the trait bound `&'a (dyn Inner + 'a): Inner` is not satisfied
  --> src/lib.rs:13:9
   |
13 |         &mut self.inner
   |         -^^^^^^^^^^^^^^
   |         |
   |         the trait `Inner` is not implemented for `&'a (dyn Inner + 'a)`
   |         help: consider removing 1 leading `&`-references
   |
   = note: required for the cast to the object type `dyn Inner`

这是公平的,所以让我们按照建议,好吗?

与此更改相同:

pub fn get_inner_mut(&mut self) -> &mut Inner {
    mut self.inner
}
error: expected expression, found keyword `mut`
  --> src/lib.rs:13:9
   |
13 |         mut self.inner
   |         ^^^ expected expression

(找到关键字mut是我的本地编译器所说的,而不是下面操场链接中的那个!)

嗯,有道理,对吗?单凭mut不是表达

但是如何返回一个可变参考呢?

好的,我们试试一下,好吗?

pub fn get_inner_mut(&mut self) -> &mut &Inner {
    &mut &self.inner
}

(注意,改变了签名!)

导致:

error[E0308]: mismatched types
  --> src/lib.rs:13:9
   |
13 |         &mut &self.inner
   |         ^^^^^^^^^^^^^^^^ lifetime mismatch
   |
   = note: expected type `&mut &dyn Inner`
              found type `&mut &'a (dyn Inner + 'a)`
note: the anonymous lifetime #1 defined on the method body at 12:5...
  --> src/lib.rs:12:5
   |
12 | /     pub fn get_inner_mut(&mut self) -> &mut &Inner {
13 | |         &mut &self.inner
14 | |     }
   | |_____^
note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 7:6
  --> src/lib.rs:7:6
   |
7  | impl<'a> Thing<'a> {
   |      ^^

这一切都可以通过指定生命周期来解决吗?

这是the playground

答案

我看到的主要问题是Thing只有inner的不可变引用。

以下是我对此的看法:

pub trait Inner {}

pub struct Thing<'a> {
    inner: &'a mut Inner,
}

impl<'a> Thing<'a> {
    pub fn get_inner(&self) -> &Inner {
        self.inner
    }

    pub fn get_inner_mut(&mut self) -> &mut Inner {
        &mut *self.inner
    }
}

struct SomeInner {}

impl Inner for SomeInner {}

fn main() {
    let mut inner = SomeInner {};
    let mut thing = Thing { inner: &mut inner };

    let inner: &Inner = thing.get_inner();
    let mutable_inner: &mut Inner = thing.get_inner_mut();
}

它编译(你可以验证on the playground

注意:

  • let mut inner = SomeInner {} - > inner是可变的
  • let mut thing - > thing也是可变的
  • &mut *self.shape - >我正在取消引用该引用,然后再次创建一个可变引用

我相信有更复杂的解决方案,我希望其他人能做出贡献。

编辑:正如Shepmaster亲切地指出的那样,根本不需要写&mut *self.shape。由于我们已经可以访问一个可变引用,只需返回self.inner就足够了 - 编译器将确保可变性得到尊重。

最后,我的尝试将成为:

impl<'a> Thing<'a> {
   pub fn get_inner(&self) -> &Inner {
     self.inner
   }

   pub fn get_inner_mut(&mut self) -> &mut Inner {
      self.inner
   }
}

Full example on playground

以上是关于在“get_trait_mut”中返回对trait的可变引用的主要内容,如果未能解决你的问题,请参考以下文章

Rust impl trait

traits的介绍

c++stl中的iterator 和 iterator_traits

scala 抽象类和trait的区别

PHP中用Trait封装单例模式的实现

什么是 Trait