FatalCatharsis
FatalCatharsis

Reputation: 3567

How to use a trait object to refer to struct that has generic methods

In relation to this question, Storing a closure in a HashMap, I learned that properly passing closures to a function requires the function to be generic and take any type that implements the Fn, FnMut, or FnOnce trait.

In implementing part of a library from C++ as a learning exercise, I require some type abstraction kind of like this.

use std::collections::HashMap;

struct Event;

trait IObject {
    fn makeFunc<F : FnMut(&Event)>(&mut self, s : &str, f : F);
}

struct Object1<'a> {
    m_funcs : HashMap<String, Box<FnMut(&Event) + 'a>>
}

impl <'a> Object1<'a> {
    fn new() -> Object1<'a> {
        Object1 {m_funcs : HashMap::new()}
    }
}

impl <'a> IObject for Object1<'a> {
    fn makeFunc<F : FnMut(&Event) + 'a>(&mut self, s: &str, f: F) {
        self.m_funcs.insert(String::from_str(s), Box::new(f));
    }
}

fn main() {
    let obj : &IObject = &Object1::new();
    println!("Hello, world!");
}

However, the error returned says that IObject cannot be a trait object because it contains a method with generic parameters. However, to pass a closure to a function at all, I require generics. Can someone show me how to achieve the abstraction I'm looking for while still being able to pass closures to functions?

Upvotes: 5

Views: 1695

Answers (1)

Chris Morgan
Chris Morgan

Reputation: 90852

You cannot get around this; static and dynamic dispatch do not mix. The monomorphisation that static dispatch (generics) does simply cannot work with the vtable used in dynamic dispatch (trait objects).

One of the two will have to go: either the usage of IObject as a trait object, or the generic function argument, in favour of accepting a Box<FnMut(&Event) + 'a>.

By the way, note how your IObject implementation is not matching the trait—the trait gives no lifetime bound on F, where your implementation does. You’d need to add 'a as a generic on the trait definition anyway (generic lifetimes are OK with trait objects).

Upvotes: 6

Related Questions