I need to create a vector of references, but it seems like this is incredibly difficult in Rust. This is a simplified version of my current implementation:
struct Object {
// stuff
}
fn f(o: Object) -> Object {
// do stuff
o
}
fn main() {
let vector = vec![Object {}, Object {}];
let mut objects: Vec<Object> = vec![];
let mut object_refs: Vec<&Object> = vec![]; // <-- this is what I need
for object in vector {
objects.push(f(object));
}
for i in 0..objects.len() {
object_refs.push(&objects[i]);
}
}
Is there a better way to do this?
Here is a link to a rust playground: https://play.rust-lang.org/?gist=2755aa64d96e0632e47488ab10908979&version=stable&backtrace=0
UPDATE
Thank you for pointing me to that question. I had actually already consulted that post, and found that it did not exactly solve my problem.
Here is how I adapted each 'version' proposed in the top answer for that question:
let v2: Vec<&Object> = v.iter().map(|s| &f(s)).collect();
let v3: Vec<&Object> = v.iter().map(|s| f(s)).map(std::ops::Deref::deref).collect();
let v4: Vec<&Object> = v.iter().map(|s| f(s) as &Object).collect();
let v5: Vec<&Object> = v.iter().map(|s| &f(s)[..]).collect();
let v6: Vec<&Object> = v.iter().map(|s| { let s: &Object = &f(s); s }).collect();
let v7: Vec<&Object> = v.iter().map(|s| f(s).as_ref()).collect();
let v8: Vec<&str> = v.iter().map(|s| f(s)).map(AsRef::as_ref).collect();
Some of these versions are clearly intended exclusively for &String
types but I've included them for the sake of completeness. You can run them in this rust playground, and verify that they all throw errors:
https://play.rust-lang.org/?gist=cc3c8fb1f774f230ad07cdd708aed044&version=stable&backtrace=0
It may also be worth mentioning that the Object
struct is actually a type imported from an external crate, so I cannot modify it in any way.
The fundamental problem is that the scope of f(s)
is inside the iterator. If you use the closure |s| &f(s)
, then f(s)
gets freed too soon:
error: borrowed value does not live long enough
--> <anon>:22:49
|
22 | let v2: Vec<&Object> = v.iter().map(|s| &f(s)).collect();
| ---^
| | |
| | temporary value dropped here while still borrowed
| temporary value created here
...
29 | }
| - temporary value needs to live until here
My original attempt involved storing the actual f(s)
values at the top level in one array and then creating a second array with references to the first. It works, but it is very verbose and awkward. If you can point out a better way, I would appreciate it.