如何使用特征对象来引用具有泛型方法的结构 [英] How to use a trait object to refer to struct that has generic methods
问题描述
关于这个问题,在 HashMap 中存储闭包,我了解到,正确地将闭包传递给函数需要该函数是泛型的,并采用实现 Fn、FnMut 或 FnOnce 特征的任何类型.
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.
在从 C++ 实现库的一部分作为学习练习时,我需要一些类似这样的类型抽象.
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!");
}
但是,返回的错误表明 IObject 不能是 trait 对象,因为它包含一个带有泛型参数的方法.但是,要将闭包传递给函数,我需要泛型.有人可以告诉我如何在仍然能够将闭包传递给函数的同时实现我正在寻找的抽象吗?
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?
推荐答案
你无法解决这个问题;静态和动态调度不混合.静态分派(泛型)所做的单态化根本无法与动态分派(特征对象)中使用的 vtable 一起使用.
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).
两者之一将不得不去:要么使用 IObject
作为特征对象,要么使用泛型函数参数,以支持接受 Box<FnMut(&Event) + 'a>
.
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>
.
顺便说一下,请注意您的 IObject
实现如何与 trait 不匹配——该 trait 没有在 F
上提供生命周期限制,而您的实现却有.无论如何,您需要在特征定义中添加 'a
作为泛型(泛型 lifetimes 对于 trait 对象是可以的).
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).
这篇关于如何使用特征对象来引用具有泛型方法的结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!