【问题标题】:How to make a vector of boxed trait objects from another vector of them?如何从它们的另一个向量制作盒装特征对象的向量?
【发布时间】:2016-05-29 11:38:44
【问题描述】:

我正在制作一个机器人。当机器人收到消息时,它需要检查所有命令是否触发消息,如果是,则执行操作。

所以我在主结构中有一个命令向量(Command trait):

struct Bot {
    cmds: Vec<Box<Command>>,
}

一切都很好,直到我尝试列出触发命令并稍后在(&amp;self mut) 方法中使用它们:

let mut triggered: Vec<Box<command::Command>>;
for c in &self.cmds {
    if c.check(&message) {
        triggered.push(c.clone());
    }
}

错误:

bot.rs:167:44: 167:56 error: mismatched types:
 expected `Box<Command>`,
    found `&Box<Command>`
(expected box,
    found &-ptr) [E0308]

我在这里做错了什么?我尝试了很多,但没有任何帮助。 最初我在做以下事情:

for c in &self.cmds {
    if c.check(&message) {
        c.fire(&message, self);
    }
}

但它给了我:

bot.rs:172:46: 172:50 error: cannot borrow `*self` as mutable because `self.cmds` is also borrowed as immutable [E0502]
bot.rs:172        

                 c.fire(&message, self);

所以我stackoverflowed它并来到了上面的解决方案。

【问题讨论】:

  • 请提供minimal reproducible example 以允许其他人重现您遇到的问题。否则,我们必须做出如此多的猜测来构建代码,我们可能会产生错误的东西。
  • 首先,您可能不应该创建 Vec>,因为向量会将其所有元素都分配到堆上,因此再次装箱只会减慢元素创建速度.

标签: vector rust borrow-checker


【解决方案1】:

我在这里做错了什么?我尝试了很多,但没有任何帮助。最初我在做以下事情:

for c in &self.cmds {
    if c.check(&message) {
        c.fire(&message, self);
    }
}

如果fire 函数不需要访问其他命令,一个选项是暂时将self.cmd 替换为空向量:

trait Command {
    fn check(&self, message: &str) -> bool;
    fn fire(&mut self, bot: &Bot);
}

struct Bot {
    cmds: Vec<Box<Command>>,
}

impl Bot {
    fn test(&mut self, message: &str) {
        use std::mem;
        // replace self.cmds with a empty vector and returns the
        // replaced vector
        let mut cmds = mem::replace(&mut self.cmds, Vec::default());
        for c in &mut cmds {
            if c.check(message) {
                c.fire(self);
            }
        }
        // put back cmds in self.cmds
        mem::replace(&mut self.cmds, cmds);
    }
}

有other answers使用这种方法。


如果fire确实需要访问Bot的某些字段,您可以只传递需要的字段而不是self:

c.fire(self.others)

【讨论】:

  • OP 声明 Command 是一个特征,而不是一个结构。这就是我想要一个 MCVE 的原因......但是,你的后半部分可能是正确的解决方案。您应该解释为什么在迭代 self.messages 时传递 self 无效 - fire 可能如何尝试修改 messages。或者,OP 可以分解 self 并仅将字段子集传递给 fire。
  • @Shepmaster 感谢提醒我Command 是一个特征。我已经习惯于查看问题何时不提供 MCVE ...在这里僵硬。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-07
  • 2022-01-25
  • 2016-05-15
  • 1970-01-01
  • 2021-02-23
相关资源
最近更新 更多