I have a vector Vec<Box<dyn SomeTrait>>, because I want to split it into many pieces in a recursive function, I need to split one vector into two half parts each time.
Is there a way that can split a vector like this at some index without allocating new memory?
As Box<dyn SomeTrait> doesn’t have Copy or Clone trait, I guess when splited, the owner of the vector would be changed.
>Solution :
Is there a way that can split a vector like this at some index without allocating new memory?
It looks like you need some views (i.e. slices) on the existing vector.
Creating another vector holding some elements from the original one will require a new memory allocation: the heap storage for the elements of the second vector (the boxes themselves, not the objects these boxes point to, these latter won’t move).
Here is a trivial example in which regular slices taken from the original vector will be problematic (exclusive and shared reference to the original vector at the same time), and a solution using split_at_mut().
Splitting each sub-part recursively (for your specific program) will always refer to the original storage of the initial vector, without any new dynamic allocation.
trait SomeTrait: std::fmt::Debug {
fn get_something(&self) -> &str;
fn change_something(
&mut self,
txt: &str,
);
}
#[derive(Debug)]
struct SomeStruct {
text: String,
}
impl SomeTrait for SomeStruct {
fn get_something(&self) -> &str {
self.text.as_str()
}
fn change_something(
&mut self,
txt: &str,
) {
self.text.push_str(txt);
}
}
fn some_function(
head: &[Box<dyn SomeTrait>],
tail: &mut [Box<dyn SomeTrait>],
) {
tail.iter_mut().for_each(|elem| {
if let Some(pos) = head
.iter()
.position(|e| e.get_something() == elem.get_something())
{
elem.change_something(&format!(" found at {}", pos));
}
});
}
fn main() {
let mut v: Vec<Box<dyn SomeTrait>> = Vec::new();
for i in 0..6 {
v.push(Box::new(SomeStruct {
text: format!("text {}", i % 3),
}))
}
let mid = v.len() / 2;
//
// some_function(&v[0..mid], &mut v[mid..]); // error!
//
let (head, tail) = v.split_at_mut(mid);
some_function(head, tail);
//
println!("{:#?}", v);
}
/*
[
SomeStruct {
text: "text 0",
},
SomeStruct {
text: "text 1",
},
SomeStruct {
text: "text 2",
},
SomeStruct {
text: "text 0 found at 0",
},
SomeStruct {
text: "text 1 found at 1",
},
SomeStruct {
text: "text 2 found at 2",
},
]
*/