rust - 如何基于 `&[Box<dyn CustomTrait>]` 创建向量?

标签 rust

我有一个自定义特征,用作切片中的元素类型:

pub trait IConstraint {
  // members here
}

pub struct Scenario<'a> {
  pub constraints: &'a [Box<dyn IConstraint>]
}

我想提供 add_constraint执行切片写时复制的方法。像这样的事情:

impl<'a> Scenario<'a> {
    pub fn add_constraint(&mut self, constraint: Box<dyn IConstraint<TNodeState>>) {
        let mut constraints: Vec<Box<dyn IConstraint<TNodeState>>> = Vec::new();
        constraints.copy_from_slice(self.constraints);
        constraints.push(constraint);
        self.constraints = &constraints;
    }
}

问题是我收到此错误:

the trait bound Box<dyn IConstraint<TNodeState>>: std::marker::Copy is not satisfied the trait std::marker::Copy is not implemented for Box<dyn IConstraint<TNodeState>>

好的,那么 Box<T>没有实现Copy特征。很公平。但我该如何解决这个问题呢?理想情况下,我会重用这些框或至少重用约束,因为它们是不可变的。但如果由于 Rust 所有权规则我无法做到这一点,我该如何实现 Copy盒子类型的特征?我尝试了各种方法,但都出现错误。

此尝试会产生“带有析构函数的类型不允许复制”:

impl<TNodeState> Copy for Box<dyn IConstraint<TNodeState>> {
}

克隆怎么样?我可以切换到constraints.clone_from_slice(self.constraints); ,但随后实现 Clone IConstraint 上的特征产生一堆“IConstraint 无法成为对象”错误。

即使我可以让盒子可克隆,那么我当然会从我的 add_constraint 中得到预期的借用生命周期缺陷。方法:

borrowed value does not live long enough

所以我必须扔掉我的 add_constraint完全使用 idea 并强制我的结构的所有者手动复制它?鉴于我的实际结构包含 3 个字段,这会变得很乏味,因为所有者现在必须将字段解构为局部变量,以便删除不可变的借用,从而允许原始向量发生突变:

fn add_remove_constraint() {
    let mut scenario = Scenario::<&str, bool, 3_usize>::new(&["A", "B", "C"]);
    let mut constraints: Vec<Box<dyn IConstraint<bool>>> = Vec::new();
    constraints.push(Box::new(SelectionCountConstraint {
        nodes: [1, 2],
        min: 1,
        max: 2,
    }));
    scenario = Scenario {
        constraints: &constraints,
        ..scenario
    };

    assert_eq!(1, scenario.get_constraints().len());
    let nodes = scenario.nodes;
    let selection_state = scenario.selection_state;
    constraints.pop();
    scenario = Scenario {
        constraints: &constraints,
        nodes,
        selection_state,
    };
    assert_eq!(0, scenario.get_constraints().len());
}

最佳答案

我认为你完全错了。正如评论中所说,您的 add_constraint永远不会工作,因为您首先引用了在同一函数中创建的内容(该函数将在函数作用域到期后被删除)。

您应该拥有一个容器来覆盖那些 IConstraint特征,但在里面你应该有一个 &dyn IConstraintBox<dyn IConstraint> .

在这种情况下,向其中添加项目是微不足道的:

pub trait IConstraint {
  // members here
}

pub struct Scenario<'a> {
  pub constraints: Vec<&'a dyn IConstraint>
}

impl<'a> Scenario<'a> {
    pub fn add_constraint(&mut self, constraint: &'a dyn IConstraint) {
        self.constraints.push(constraint);
    }
}

Playground

这应该可以解决您的问题,因为引用是 Copy

关于rust - 如何基于 `&[Box<dyn CustomTrait>]` 创建向量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72437343/

相关文章:

rust - 将包含引用的结构移动到静态闭包中不起作用

rust - 为什么这个值在上次使用后没有下降?

rust - 我可以创建一个指向堆栈对象的拥有指针吗

macros - 宏观规则!宏采用字符串文字 "...",扩展为 "..."和 b"..."

rust - 生命周期阻碍了状态机返回到最近的状态

c++ - 在 Rust 中捕获循环计数器拷贝的函数

rust - 有没有办法查看我的项目中所有依赖于另一个 crate 的 crate ?

rust - .next() 之后 for ... .zip() : Preventing iterator from being moved

rust - 如何使用引用箱发出具有非十进制基数的整数文字?

rust - 为什么在使用 Regex 映射字符串时显然需要 std::borrow::Cow?