如何为持有闭包的Rust结构体实现默认构造函数
解决Rust持有闭包的结构体实现默认构造函数的问题
问题原因
你当前的default函数试图返回一个特定闭包类型的Computation,但泛型参数F是由调用者指定的——每个闭包都有唯一的匿名类型,无法匹配任意传入的F类型,因此编译器抛出类型不匹配的错误。
解决方案
方案一:为函数指针类型实现Default trait
指定F为函数指针类型fn(&X) -> Y,并约束Y实现Default,让默认构造函数返回一个返回Y默认值的函数指针:
use std::marker::PhantomData; struct Computation<X, Y, F> where F: Fn(&X) -> Y, { f: F, _p: PhantomData<(X, Y)>, } impl<X, Y, F> Computation<X, Y, F> where F: Fn(&X) -> Y, { fn new(f: F) -> Self { Computation { f, _p: PhantomData, } } } // 为函数指针类型的F实现Default,要求Y能生成默认值 impl<X, Y> Default for Computation<X, Y, fn(&X) -> Y> where Y: Default, { fn default() -> Self { // 定义默认计算函数 fn default_compute<X, Y: Default>(_input: &X) -> Y { Y::default() } Computation::new(default_compute) } } // 使用示例 fn main() { // 显式指定类型 let comp: Computation<i32, (), fn(&i32) -> ()> = Default::default(); // 或让编译器推导类型 let comp = Computation::<String, u32, _>::default(); }
方案二:用关联函数返回具体闭包类型的实例
单独实现一个关联函数,利用impl Trait隐藏闭包的具体类型,同时约束Y实现Default以生成空计算的返回值:
use std::marker::PhantomData; struct Computation<X, Y, F> where F: Fn(&X) -> Y, { f: F, _p: PhantomData<(X, Y)>, } impl<X, Y, F> Computation<X, Y, F> where F: Fn(&X) -> Y, { fn new(f: F) -> Self { Computation { f, _p: PhantomData, } } } // 针对X和Y实现默认构造函数,返回带闭包的Computation impl<X, Y> Computation<X, Y, impl Fn(&X) -> Y> where Y: Default, { fn default() -> Self { Computation::new(|_| Y::default()) } } // 使用示例 fn main() { let comp = Computation::<i32, ()>::default(); // 调用计算 (comp.f)(&42); // 返回() }
方案三:使用类型擦除简化结构体设计
将闭包包装在Box<dyn Fn(&X)->Y>中,去掉结构体的F泛型参数,代价是引入堆分配和动态分发,但实现Default会更简洁:
use std::marker::PhantomData; struct Computation<X, Y> { f: Box<dyn Fn(&X) -> Y>, _p: PhantomData<(X, Y)>, } impl<X, Y> Computation<X, Y> { fn new<F: Fn(&X) -> Y + 'static>(f: F) -> Self { Computation { f: Box::new(f), _p: PhantomData, } } } impl<X, Y: Default> Default for Computation<X, Y> { fn default() -> Self { Computation::new(|_| Y::default()) } } // 使用示例 fn main() { let comp: Computation<i32, String> = Default::default(); println!("{}", (comp.f)(&123)); // 打印空字符串 }
内容的提问来源于stack exchange,提问作者lighthouse
相关产品推荐
相关产品推荐

