如何基于 `&[Box<dyn CustomTrait>]` 创建向量?
How to create a vector based on an `&[Box<dyn CustomTrait>]`?
我有一个自定义特征,用作切片中的元素类型:
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);
,但随后在 IConstraint
上实现 Clone
特性会产生一堆“IConstraint 无法成为对象”错误。
即使我能让 box 成为可克隆的,那么我当然会从我的 add_constraint
方法中得到预期的借用生命周期缺陷:
borrowed value does not live long enough
所以我是否必须完全放弃我的 add_constraint
函数想法并强制我的结构的所有者手动复制它?考虑到我的实际结构包含 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 IConstraint
或 Box<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);
}
}
这应该可以解决您的问题,因为 参考文献是 Copy
。
我有一个自定义特征,用作切片中的元素类型:
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 traitstd::marker::Copy
is not implemented forBox<dyn IConstraint<TNodeState>>
好的,所以 Box<T>
没有实现 Copy
特性。很公平。但是我该如何解决呢?理想情况下,我会重用这些框或至少是约束,因为它们是不可变的。但是如果由于 rust 所有权规则我不能这样做,我怎么能在盒子类型上实现 Copy
特性呢?我尝试了各种方法,但它们都会产生错误。
此尝试产生“在具有析构函数的类型上不允许复制”:
impl<TNodeState> Copy for Box<dyn IConstraint<TNodeState>> {
}
克隆呢?我可以切换到 constraints.clone_from_slice(self.constraints);
,但随后在 IConstraint
上实现 Clone
特性会产生一堆“IConstraint 无法成为对象”错误。
即使我能让 box 成为可克隆的,那么我当然会从我的 add_constraint
方法中得到预期的借用生命周期缺陷:
borrowed value does not live long enough
所以我是否必须完全放弃我的 add_constraint
函数想法并强制我的结构的所有者手动复制它?考虑到我的实际结构包含 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 IConstraint
或 Box<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);
}
}
这应该可以解决您的问题,因为 参考文献是 Copy
。