Hi all,
I have a coding problem and am stuck. I have a struct and want to call its associated functions depending on a string that I get from somewhere else. I know that I could have a big match statement that calls the correct function, but I don't like that this has so much boilerplate.
My idea was to use a std HashMap to pair a string with the respective member function. After some fiddling with the lifetime parameters I got it to compile, but now I'm getting a "cannot borrow as mutable more than once at a time" and I don't understand why. Here is the code:
use std::collections::HashMap;
type MemberType<'a, 'b> = fn(&'b mut SomeStruct<'a, 'b>, i32);
struct SomeStruct<'a, 'b> {
ref_val: &'a i32,
value: i32,
function_map: HashMap<String, MemberType<'a, 'b>>
}
impl<'a, 'b> SomeStruct<'a, 'b> {
fn change_value(&mut self, new_value: i32) {
println!("Value: {}", self.value);
self.value = new_value;
self.ref_val = &8;
}
fn change_value_2(&mut self, new_value: i32) {
println!("Value2: {}", self.value);
self.value = new_value;
}
fn call_function(self: &'b mut SomeStruct<'a, 'b>, function_name: String) {
let function = self.function_map.get(&function_name).unwrap();
function(self, 1);
}
fn increment(&mut self) {
self.value += 1;
}
}
fn main() {
let number = 5;
let mut test_map: HashMap<String, MemberType> = HashMap::new();
test_map.insert("change_value".to_string(), SomeStruct::change_value as MemberType);
test_map.insert("change_value_2".to_string(), SomeStruct::change_value_2 as MemberType);
let mut some_struct = SomeStruct {
ref_val: &number,
value: 0,
function_map: test_map
};
some_struct.increment();
some_struct.increment();
some_struct.call_function("change_value".to_string());
some_struct.call_function("change_value_2".to_string());
println!("Number: {}", number);
}
The error occurs on the second call to call_function
.
Some context: I gave SomeStruct
2 lifetime parameters, because I didn't find another way to cast the Member functions into something that can be put into a HashMap. If I don't explicitly specify a type for the Hashmap, the compiler will treat SomeStruct::change_value
as a function item and not a function pointer. I added increment
to show that mutably borrowing works normally otherwise and the print statement to make sure that the lifetime of the borrowed value is long enough.
Any help is appreciated!