在Rust中,我可以返回带有捕获的可变引用的FnMut吗,也许可以通过指定泛型生命周期?

2uluyalo  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(90)

是否可以在Rust中为这样的函数在FnMut上指定一个泛型生存期?

fn f1<'a, FRet:'a + FnMut() -> ()>(v: &'a mut i32) -> FRet {
   let mut fret = || {
       let i = v;
       println!("inside");
       // lots of complicated logic on captured var
       *i = 5;
   };

   return fret;
}

现在我得到一个错误,返回与FRet不兼容。

wribegjk

wribegjk1#

你的代码有几个问题。一个是不能让返回闭包的函数具有泛型返回类型。f1FRet通用意味着调用者可以选择FRet,当你返回一个你实现的闭包时,这显然是行不通的,而不是调用者可以或应该指定的东西。这就是为什么编译器会抱怨FRet与您实际返回的内容不兼容。
返回闭包的方法是将其装箱或使用impl Trait返回类型,该类型声明函数返回的未命名类型:

fn f1(v: &mut i32) -> impl FnMut() {
   let fret = || {
       let i = v;
       println!("inside");
       // lots of complicated logic on captured var
       *i = 5;
   };

   fret
}

上面的代码仍然无法编译,编译器抱怨闭包是FnOnce而不是FnMut。这是因为&mut i32不是Copy,所以let i = v实际上将引用移出了v,这使得闭包只能调用一次。这可以通过再借款来解决,即。将let i = v更改为let i = &mut *v
之后,编译器会抱怨闭包没有捕获引用的生存期,你可以通过添加+ '_来修复这个问题。(这相当于声明了一个生存期'a,并声明了v: &'a mut i32impl FnMut() + 'a。)通过此更改,代码编译:

fn f1(v: &mut i32) -> impl FnMut() + '_ {
   let fret = || {
       let i = &mut *v;
       println!("inside");
       // lots of complicated logic on captured var
       *i = 5;
   };

   fret
}

Playground

相关问题