Reputation: 35
use std::collections::BTreeMap;
#[derive(Debug)]
struct TestStruct {
name: String,
num: f64,
}
fn main() {
let test_struct = TestStruct {name: "Test".to_string(), num: 0.42 };
println!("{:?}", test_struct);
}
fn get_fields_as_map(test_struct: &TestStruct) -> BTreeMap<&str, &str> {
let mut field_map: BTreeMap<&str, &str> = BTreeMap::new();
field_map.insert("name", &test_struct.name);
field_map.insert("num", &test_struct.num.to_string());
field_map
}
This generates the error:
error[E0515]: cannot return value referencing temporary value
--> src/main.rs:19:5
|
18 | field_map.insert("num", &test_struct.num.to_string());
| --------------------------- temporary value created here
19 | field_map
| ^^^^^^^^^ returns a value referencing data owned by the current function
Which I think makes sense. The to_string()
function is allocating a string whose lifetime is that of the function. What I haven't figured out is how to allocate the string such that it has the same lifetime as the BTreeMap
. I've tried several different ways without success and feel I'm missing something. I don't fully understand ownership.
Upvotes: 3
Views: 2587
Reputation: 361977
You can avoid the headache if you let the map own the strings inside it rather than store references. References mean lifetimes are involved, and as you've found it's difficult to construct &str
s with the required lifetimes.
Change the &str
references to owned String
s and life is easy:
fn get_fields_as_map(test_struct: &TestStruct) -> BTreeMap<String, String> {
let mut field_map = BTreeMap::new();
field_map.insert("name".to_owned(), test_struct.name.to_owned());
field_map.insert("num".to_owned(), test_struct.num.to_string());
field_map
}
Upvotes: 8