Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a struct with a vector of references?

Rust seems like such an optimal language - I should've known fighting the compiler would be the price. I'm trying to create a constructor for a struct, and I'm getting does not live long enough errors.

Distilled to the barest of bones, I have:

fn main() {
    println!("RUST PLEASE");
}

struct Help<'a> {
    list: Vec<&'a Traits>
}

impl<'a> Help<'a> {
    fn new() -> Help<'a> {
        Help { list: vec![&Test] }
    }
}

trait Traits {
    fn mice(&self);
}

struct Test;
impl Traits for Test {
    fn mice(&self) { print!("WHY"); }
}

So, I'm doing this because that vector list is supposed to hold a list of trait objects. It (supposedly) holds heterogeneously any class that implements the supplied trait. As I understand it, that means I have to use references so the vector has a real size to work with. And since it's a reference, the lifetime has to be there to ensure they live and die together.

The thing is, I know what's wrong. In new, that Test belongs in the new scope, and I try to pass its reference up and out of the function. If I do that, Test goes out of scope and the reference is bad. So what do I do? How can I get the object to last the lifetime of Help? After all, there's really no one to own it.

Also, if anybody has any tips in general on how to return references out of a function in general, I'd be very happy to hear them.

EDIT This is not the same as simply passing up ownership of the object; I can't do that because the vector needs a reference instead of an object on the stack. The answer by Simon is probably what I'm looking for - I had forgotten I could box things up like that.

like image 972
Jason Tan Avatar asked Mar 24 '16 01:03

Jason Tan


People also ask

How do you create a struct vector?

To create a vector of structs, define the struct, with a generalized (class) name. Make the template argument of the vector of interest, the generalized name of the struct.

Can I use vector in struct?

You can actually create a vector of structs!

Can you make a reference vector?

References are not assignable (you can only initialize them once when they are declared, and you cannot make them reference something else later). Other non-assignable types are also not allowed as components of containers, e.g. vector<const int> is not allowed.

Can std::vector hold references?

std::reference_wrapper It is frequently used as a mechanism to store references inside standard containers (like std::vector) which cannot normally hold references.


1 Answers

You probably don't actually want to return references out... but you could box them instead and have them own the boxed value:

fn main() {
    println!("RUST PLEASE");
}

struct Help {
    list: Vec<Box<Traits>>
}

impl Help {
    fn new() -> Help {
        Help { list: vec![Box::new(Test)] }
    }
}

trait Traits {
    fn mice(&self);
}

struct Test;
impl Traits for Test {
    fn mice(&self) { print!("WHY"); }
}

Your Help struct then owns a vector of boxed values that you can then reference going forward.

Playpen link

like image 112
Simon Whitehead Avatar answered Oct 02 '22 06:10

Simon Whitehead