Rust中泛型仅出现在trait bound的结构体定义问题求解
问题
尝试定义一个存储FnMut(&E)类型值的结构体:
struct Publisher<E,F> where F: FnMut(&E) { subscribers: Vec<F> }
但Rust编译器报错称E未被使用,而省略E又会因E未知导致编译失败。虽然可以通过虚数据PhantomData解决:
struct Publisher<E,F> where F: FnMut(&E) { subscribers: Vec<F>, event: core::marker::PhantomData<E> }
但这种方式不够优雅,请问正确的解决方法是什么?
解决方法
方式一:将E移至impl块的泛型约束
不需要把E作为结构体的泛型参数,而是在实现结构体方法时,通过F的约束引入E:
struct Publisher<F> { subscribers: Vec<F>, } impl<F, E> Publisher<F> where F: FnMut(&E), { // 发布事件方法示例 fn publish(&mut self, event: &E) { for subscriber in &mut self.subscribers { subscriber(event); } } // 添加订阅者方法示例 fn subscribe(&mut self, subscriber: F) { self.subscribers.push(subscriber); } }
这种方式下,结构体仅关注订阅者类型F,E的类型会在调用publish时自动推导,既规避了未使用泛型的报错,也无需额外的虚数据字段。
方式二:优化PhantomData的写法(保留E作为泛型参数)
如果需要在结构体的类型签名中明确体现事件类型E,可以使用更简洁且语义准确的PhantomData写法:
use core::marker::PhantomData; struct Publisher<E, F> where F: FnMut(&E), { subscribers: Vec<F>, // 下划线开头标记为无需使用的字段,&E贴合FnMut(&E)的语义,表达协方差 _event: PhantomData<&E>, }
_event的命名会让编译器忽略未使用字段的警告,PhantomData<&E>相比直接使用PhantomData<E>更符合场景语义,还能正确表达类型的方差特性,避免潜在的安全问题。
内容的提问来源于stack exchange,提问作者Henning Koehler
相关产品推荐
相关产品推荐

