Rust实现策略模式时报匿名函数生命周期冲突无法推断错误
问题根因
你遇到的错误和Outer本身的生命周期无关,核心是Rust对trait对象的默认生命周期规则:
- 未显式标注生命周期的
Box<dyn Trait>类型,默认会被加上'static生命周期约束
你原本的代码里,返回的Box<dyn FnMut() -> Outer>默认要求'static,但你返回的闭包捕获了传入的inners引用,这个引用的生命周期远短于'static,因此触发冲突。
你修改后的泛型生命周期版本依然报错,是因为你只标注了输入参数的生命周期,没有把返回的闭包trait对象的生命周期和输入参数绑定,编译器依然默认要求返回的闭包满足'static,自然会要求输入的inners生命周期为'static,和你栈上创建的inners生命周期不匹配。
修复方案
你只需要显式把返回的闭包生命周期和输入的inners生命周期绑定即可,不需要克隆整个inners列表:
- 给
Strategy类型别名的返回值加上生命周期约束,明确返回的闭包的有效期和输入的Inner列表一致 - 注意调用
FnMut类型的闭包需要声明可变变量,完整可运行代码如下:
use rand::{prelude::SliceRandom, Rng}; #[derive(Debug, Clone)] struct Inner { num: usize, } #[derive(Debug)] enum Outer { ActionA(Inner), ActionB(Inner), } fn main() { // 显式标注生命周期:返回的闭包有效期和输入的Inner列表一致 type Strategy<'a> = Box<dyn Fn(&'a [&'a Inner]) -> Box<dyn FnMut() -> Outer + 'a>>; let random_strategy: Strategy = Box::new(|inners| { let mut rng = rand::thread_rng(); Box::new(move || { let inner = inners.choose(&mut rng).unwrap(); if rng.gen_bool(1.0 / 2.0) { Outer::ActionA(inner.to_owned().clone()) } else { Outer::ActionB(inner.to_owned().clone()) } }) }); let inners = vec![&Inner { num: 3 }, &Inner { num: 4 }]; let mut get_choice = random_strategy(&inners); for _ in 0..4 { let choice = get_choice(); println!("{:?}", choice); // do something... } }
这个方案里闭包只会持有inners的不可变引用,不会对列表做拷贝,完全符合你的需求。编译器会自动校验get_choice的使用范围不会超过inners的生命周期,你当前的main函数逻辑完全满足这个要求。
内容的提问来源于stack exchange,提问作者user82395214
相关产品推荐
相关产品推荐

