Simulate dynamic dispatch of generic functions

I'm trying to do something like:

pub trait RegisterHook {
    fn register<V>(&mut self);
}

struct Register {
    hooks: Vec<Box<dyn RegisterHook>>,
}

impl Register {
    fn add_hook<R: RegisterHook>(&mut self, hook: H) {
        self.hooks.push(Box::new(hook))
    }

    fn register<V>(&mut self) {
        for hook in &mut self.hooks {
            hook.register::<V>()
        }
    }
}

Of course this can't be done like that cause a trait with generic functions not marked as Self: Sized can't be used as a trait object but was wondering if there's a workaround to simulate that behavior in some other way.

You can often define a new trait that isn't generic but whose implementation delegates to the RegisterHook trait. However, I don't think it's possible for this particular use-case when you don't actually take any arguments of the generic type.

Could you post an example of how would you do that when passing an argument of the type?

Sure, you could do this:

use std::fmt::Display;

trait MyTrait {
    fn takes_display<T: Display>(&self, arg: &T);
}

trait MyTraitDyn {
    fn takes_display(&self, arg: &dyn Display);
}
impl<T> MyTraitDyn for T
where
    T: MyTrait,
    T: ?Sized,
{
    fn takes_display(&self, arg: &dyn Display) {
        MyTrait::takes_display(self, &arg);
    }
}

Then store an Box<dyn MyTraitDyn>.

1 Like

I see. I was just trying something like that. The problem is my parameter trait has associated types which makes this even more difficult.

As in:

trait Parameter {
    type A;
}

trait MyTrait {
    fn takes_parameter<P: Parameter>(&self, param: P);
}

Cause in the dynamic version you need to specify all the associated types which makes it pretty impractical
.
Thanks!

If it has associated types, you can sometimes do one of these:

  1. Give the associated type a fixed value.
  2. Define another helper trait that doesn't have associated types.

But sometimes you can't, and then you're out of luck.

2 Likes

Actually I'm trying this and it doesn't work. &dyn Trait`` doesn't necessarily implement Trait but also I need to preserve type information which is lost when using the object trait.

Sure, this technique only works in some cases. For the specific problem of &dyn Trait not implementing Trait, you can define a wrapper struct around the reference and implement the trait for your wrapper.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.