如何使用特质对象引用具有通用方法的结构体

5

关于这个问题,在HashMap中存储闭包,我了解到正确地将闭包传递给函数需要使该函数成为通用函数,并且接受实现了Fn,FnMut或FnOnce trait的任何类型。

作为学习练习,我正在实现C ++库的一部分,我需要某种类型抽象。

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!");
}

然而,返回的错误显示IObject不能是一个特质对象,因为它包含一个带有泛型参数的方法。但是,要将闭包传递给函数,我需要使用泛型。有人能向我展示如何实现我正在寻找的抽象化,同时仍然能够将闭包传递给函数吗?

1个回答

6
您无法绕过这个问题;静态和动态分派不兼容。静态分派(泛型)所做的单态化无法与动态分派(特质对象)中使用的虚函数表一起工作。
两者之间必须有一个被删除:要么将IObject用作特质对象,要么删除泛型函数参数,改为接受Box<FnMut(&Event) + 'a>
顺便提一下,请注意您的IObject实现未匹配到特质 - 特质在F上没有生命周期限制,而您的实现则有。无论如何,您都需要在特质定义上添加'a作为泛型(特质对象可以使用泛型生命周期)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接