包装泛型Fn时能否避免使用PhantomData?
不用PhantomData解决未使用泛型参数的方案
先看这段会报错的代码:
struct Wrapper<F:Fn(T)->(),T> { func: F }
编译器会提示T是未使用的类型参数,常规操作是加PhantomData<T>来解决,但其实还有几种不用PhantomData的办法:
把T的约束移到impl块里
结构体只保留F作为泛型参数,T的约束放在impl块中,这样结构体本身不会有未使用的泛型:struct Wrapper<F> { func: F, } impl<F, T> Wrapper<F> where F: Fn(T) -> (), { fn new(func: F) -> Self { Wrapper { func } } fn execute(&self, value: T) { (self.func)(value); } }这种方式是静态分派,没有额外开销,T的类型会在调用
execute时自动推导。用trait对象封装带T的函数
如果需要在结构体级别明确标注T,可以把函数包装成trait对象,这样T会被trait对象使用,不会触发未使用参数的错误:struct Wrapper<T> { func: Box<dyn Fn(T) -> ()>, } impl<T> Wrapper<T> { fn new(func: impl Fn(T) -> () + 'static) -> Self { Wrapper { func: Box::new(func) } } }不过这种方法会引入动态分派的开销,适合对性能要求不高或者需要动态替换函数的场景。
用关联类型绑定T和F
定义一个带关联类型的trait,让F实现这个trait来关联T,结构体只需要依赖这个trait:trait FnWithInput { type Input; fn call(&self, val: Self::Input); } impl<F, T> FnWithInput for F where F: Fn(T) -> (), { type Input = T; fn call(&self, val: T) { (self)(val); } } struct Wrapper<F: FnWithInput> { func: F, } impl<F: FnWithInput> Wrapper<F> { fn new(func: F) -> Self { Wrapper { func } } fn execute(&self, val: F::Input) { self.func.call(val); } }这种方式更灵活,适合需要复杂类型关联的场景。
内容的提问来源于stack exchange,提问作者redjamjar
相关产品推荐
相关产品推荐

