TL;DR 我如何在泛型类型上构建数据结构,这些数据结构引用共享的基础数据?
这个问题涉及到Rust中语义和良好的数据建模。下面的代码是我问题的(更)简化版本,以突出我的具体问题,而不是我的实际代码。
目标是创建一个函数,该函数构建多个向量,这些向量包含对泛型类型的共享数据的引用。在以下示例的术语中,我希望能够返回一个集合,该集合可以存储Struct1
和Struct2
(由特征Trait
抽象),但由于(在我的真实代码中)Struct1
和Struct2
相对较大,并且将被相对频繁地存储在相对许多位置,因此我宁愿存储对共享数据的引用,而不是将它们全部复制到各个位置。
我目前面临的问题(并且有许多中间修订)是:
- 由于我尝试存储的数据类型是
Trait
,而不是Sized
,因此我需要在我的向量中存储引用 - 由于每个结构将从多个向量引用,因此需要一个
&
引用 - 在哲学上,没有给定结构的“所有者”,因此没有“正确”的地方可以将我的结构放置在其中,以便它们不会随着
build_vectors
函数超出范围。- 我考虑通过
Traits
的全局向量来解决这个问题,其中我可以指向引用,但不幸的是,上述问题(1)似乎排除了该策略。
- 我考虑通过
.
struct Struct1;
struct Struct2;
trait Trait { fn name(&self) -> &str; }
impl Trait for Struct1 { fn name(&self) -> &str { "Struct1" } }
impl Trait for Struct2 { fn name(&self) -> &str { "Struct2" } }
fn shallow_copy<'a>(v: &'a Vec<&'a Box<Trait>>) -> Vec<&'a Box<Trait>> {
v.iter().map(|x|*x).collect()
}
fn build_vectors<'a>() -> (Vec<&'a Box<Trait>>, Vec<&'a Box<Trait>>) {
let box_struct1: &Box<Trait> = &(Box::new(Struct1) as Box<Trait>);
let box_struct2: &Box<Trait> = &(Box::new(Struct2) as Box<Trait>);
let vec1: Vec<&Box<Trait>> = vec![box_struct1];
let mut vec2: Vec<&Box<Trait>> = shallow_copy(&vec1);
vec2.push(box_struct2);
(vec1, vec2)
}
fn join_names(v: &Vec<&Box<Trait>>) -> String {
v.iter().map(|s| s.name()).collect::<Vec<_>>().connect(" ")
}
fn main() {
let (vec1, vec2) = build_vectors();
println!("vec1: {}", join_names(&vec1));
println!("vec2: {}", join_names(&vec2));
}
期望的输出是:
vec1: Struct1
vec2: Struct1 Struct2