0

I want to create a registry of objects that all implement some trait. So the Registry struct has a register function. But if I declare it returning void type, I can only register one object, then borrow issue for the second one. I found a work around: the register function returns self as mutable, then I an reuse the registry returned and the compiler is OK. I found this a bit ridiculous. What is the proper way to maintain a registry of objects ? Here is the code that works

trait Doable {
    fn do_it(&mut self);
}

struct Registry<'a> {
    components: Vec<Box<&'a (dyn Doable)>>,
}

impl<'a> Registry<'a> {
    fn register(&'a mut self, d: &'a impl Doable) -> &mut Registry<'a> {
        self.components.push(Box::new(d));
        self
    }
}

struct Foo {
    name: String,
    value: u32,
}
impl Foo {
    fn set_value(&mut self, v: u32) {
        self.value = v
    }
}
impl Doable for Foo {
    fn do_it(&mut self) {
        println!("The value of {} is {}", self.name, self.value);
    }
}

struct Bar {
    nm: String,
    id: u32,
}
impl Bar {
    fn set_id(&mut self, v: u32) {
        self.id = v
    }
}
impl Doable for Bar {
    fn do_it(&mut self) {
        println!("The id of {} is {}", self.nm, self.id);
    }
}

fn main() {
    let mut r = Registry {
        components: Vec::new(),
    };
    let mut foo: Foo = Foo {
        name: "foo".to_string(),
        value: 0,
    };
    let mut bar: Bar = Bar {
        nm: "bar".to_string(),
        id: 0,
    };
    let mut baz: Foo = Foo {
        name: "baz".to_string(),
        value: 0,
    };
    let r1 = r.register(&foo);
    let r2 = r1.register(&bar);
    r2.register(&baz);
    foo.set_value(41);
    bar.set_id(5);
    baz.set_value(11);
    foo.do_it();
    bar.do_it();
    baz.do_it();
}

it works but I would like to have a better way for registering objects and then call them back using the trait...

cafce25
  • 15,907
  • 4
  • 25
  • 31
Zhou Lebo
  • 31
  • 2

1 Answers1

0

The solution is to not sprinkle around lifetimes everywhere, only where needed, with

impl<'a> Registry<'a> {
    fn register(&'a mut self, d: &'a impl Doable) -> &mut Registry<'a> {

you tell the compiler that the mutable borrow lasts as long as any reference in Registry which is plain wrong. If you remove the 'a from self it works:

impl<'a> Registry<'a> {
    fn register(&mut self, d: &'a impl Doable) -> &mut Registry<'a> {
        //…
    }
}
cafce25
  • 15,907
  • 4
  • 25
  • 31