I have a number of generic functions that need to return new instances of the generic. However, the fields in the generic are not known, but I need to get/set the field values to create the instance (a simple Default will not work). For primitive fields, I can update my struct, but for fields with Vector or HashMap types, I get the error:
the size for values of type `[usize]` cannot be known at compilation time
Here is a minimal working example of my issue:
trait MyTrait {
fn id(&self) -> &usize;
fn id_mut(&mut self) -> &mut usize;
fn data(&self) -> &[usize];
fn data_mut(&mut self) -> &mut [usize];
}
#[derive(Debug)]
struct MyStruct {
id: usize,
data: Vec<usize>,
}
impl MyTrait for MyStruct {
fn id(&self) -> &usize {
&self.id
}
fn id_mut(&mut self) -> &mut usize {
&mut self.id
}
fn data(&self) -> &[usize] {
&self.data
}
fn data_mut(&mut self) -> &mut [usize] {
&mut self.data
}
}
impl Default for MyStruct {
fn default() -> MyStruct {
MyStruct {
id: 0,
data: vec![],
}
}
}
fn my_func<T: MyTrait + Default>() -> T {
let mut d = T::default();
// this correctly updates the struct field "id" to 26
*d.id_mut() = 26;
// this however, does not work. i get an error:
// the size for values of type `[usize]` cannot be known at compilation time
*d.data_mut() = vec![1, 2, 3].as_slice();
d
}
fn main() {
let _my_instance = my_func::<MyStruct>();
}
How can I create a generic function that returns an instance of the generic type?
For your Default
instance of MyStruct
, data
is an empty Vec
, but you are exposing it as a mutable slice. This is pretty meaningless because you can't change the length of a mutable slice; you can only mutate existing elements.
You will need to expose data
as a &mut Vec<usize>
instead, so that you can insert elements. The immutable getter can stay the same.
trait MyTrait {
fn id(&self) -> &usize;
fn id_mut(&mut self) -> &mut usize;
fn data(&self) -> &[usize];
fn data_mut(&mut self) -> &mut Vec<usize>;
}
And change the code that updates it:
fn my_func<T: MyTrait + Default>() -> T {
let mut d = T::default();
*d.id_mut() = 26;
*d.data_mut() = vec![1, 2, 3];
d
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.