Rust所有权:实现可Push且支持成员不可变引用的向量容器
需求:支持Push操作且可持有成员不可变引用的不可变元素容器
核心诉求
我需要一个存储不可变元素的向量,既要能持有其成员的短生命周期不可变引用,又支持向其中添加元素。
我正在开发一个替代浮点数的精确算术crate,该crate需实现Copy trait。由于表达式是递归结构,我参考了将递归层级存入Vec的实现思路。
代码示例
enum ExprData{ Val(u32), Const{ch: char, f64: f64}, Sum(Vec<(u32, ExprRef)>) } #[derive(Clone, Copy)] // 实际需要自己实现Clone,否则会尝试克隆Field或者报错Field未实现Copy struct FieldRef<'a> { index: usize, field: &'a Field } #[derive(Clone, Copy)] enum ExprRef<'a> { Val(FieldRef<'a>), Const(FieldRef<'a>), Sum(FieldRef<'a>) } struct Field { members: SpecialContainer<ExprData>, } impl Field { fn parse(&mut self, input: &str) -> ExprRef { assert_eq!(input, "π+1"); let idx0 = self.maybe_add(ExprData::Const{ch: 'π', f64: f64::consts::PI}); let idx1 = self.maybe_add(ExprData::Val(1)); let idx2 = self.maybe_add(ExprData::Sum(vec![(1,ExprRef::Const(FieldRef{field: self, index: idx0})),(1,ExprRef::Val(FieldRef{field: self, index: idx1}))])); ExprRef::Sum(FieldRef{field: self, index: idx2}) } fn maybe_add(&mut self, data: ExprData) -> usize { match self.members.position(&data) { // 需要判断相等性,用不可变引用最优;克隆求和向量效率极低 Some(p) => p, None => { self.members.push(data); // 核心矛盾点:Push操作会导致已有引用失效 self.members.len()-1 } } } } fn main () { // Field: [] let mut f = Field { members: SpecialContainer::new() }; let pi_one: ExprRef = f.parse("π+1"); // // Field: [π, 1, 1+π] let two_pi_one = pi_one + pi_one; // collect_like_terms([f.get_sum(pi_one),f.get_sum(pi_one)].concat()) // [1+π] + [1+π] -> [(1,1),(1,π),(1,1),(1,π)] -合并同类项-> [(2,1),(2,π)] // field.maybe_add(ExprData::Sum([(2,1),(2,π)]) // Field: [π, 1, 1+π, 2+2π] }
已考虑的方案
Vec<OnceCell<ExprData>>:不支持Push操作,因为Push可能会移动数据,导致已有引用失效HashSet<ExprData>:不确定扩容时是否会移动数据,无法安全插入同时保留引用RefCell<Vec<ExprData>>:每次访问都需要克隆ExprData,不符合避免克隆的需求LinkedList<[OnceCell<ExprData>; CHUNK_SIZE]>:可行,但LinkedList追加仍需可变引用,不过Push不会移动底层数据AppendList<ExprData>:功能符合需求,但实现复杂度较高- 基于
Cow的实现:暂未明确可行路径
内容的提问来源于stack exchange,提问作者Fee
相关产品推荐
相关产品推荐

