简体   繁体   English

匿名函数 - 由于需求冲突,无法推断出合适的生命周期

[英]Anonymous function - cannot infer an appropriate lifetime due to conflicting requirements

I am trying to use the strategy pattern to have different methods for generating actions from a list of input.我正在尝试使用策略模式来使用不同的方法从输入列表中生成操作。

use rand::{prelude::SliceRandom, Rng};

#[derive(Debug, Clone)]
struct Inner {
    num: usize,
}

#[derive(Debug)]
enum Outer {
    ActionA(Inner),
    ActionB(Inner),
}

fn main() {
    // A method to generate an Outer from a list of Inners
    type Strategy = Box<dyn Fn(&Vec<&Inner>) -> Box<dyn FnMut() -> Outer>>;

    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 get_choice = random_strategy(&inners);

    for _ in 0..4 {
        let choice = get_choice();
        println!("{:?}", choice);
        // do something...
    }
}

Each strategy is a closure because it may contain some state (not shown here in order to keep the example simple).每个策略都是一个闭包,因为它可能包含一些状态(为了保持示例简单,此处未显示)。

I get the compiler error我收到编译器错误

cannot infer an appropriate lifetime due to conflicting requirements
expected `(&&Vec<&Inner>, &mut ThreadRng)`
   found `(&&Vec<&Inner>, &mut ThreadRng)`
but, the lifetime must be valid for the static lifetime...
expected `Box<(dyn FnMut() -> Outer + 'static)>`
   found `Box<dyn FnMut() -> Outer>`

I'm confused as to why the output Outer must have a static lifetime.我很困惑为什么输出Outer必须具有静态生命周期。 I am creating Outer once, using a wholly-owned Inner (after cloning), returning it from the anonymous function, and never using it again in that anonymous function.我正在创建Outer一次,使用全资拥有的Inner (克隆后),从匿名函数返回它,并且不再在该匿名函数中使用它。 I would expect that the caller ( let choice = get_choice() ) would have ownership over Outer .我希望调用者( let choice = get_choice() )拥有对Outer所有权。

This question has the same error but differs because, in my example, Outer needs to own Inner . 这个问题有相同的错误,但有所不同,因为在我的例子中, Outer需要拥有Inner

I can change the strategy definition to我可以将策略定义更改为

type Strategy<'a> = Box<dyn Fn(&'a Vec<&'a Inner>) -> Box<dyn FnMut() -> Outer>>;

but then I get the error但后来我得到了错误

`inners` does not live long enough
borrowed value does not live long enoughrustcE0597
main.rs(38, 1): `inners` dropped here while still borrowed
main.rs(18, 26): type annotation requires that `inners` is borrowed for `'static`

(Line 38 is the end of the main function) (第38行是main函数的结尾)

I'm unsure how to fix this without cloning the entirety of inners each time I want to use a strategy.每次我想使用策略时,我不确定如何在不克隆整个内部的情况下解决这个问题。

The problem is that问题是

        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())
            }
        }

captures inners , which is the &Vec<&Inner> you passed in to the outer closure.捕获inners ,这是您传递给外部闭包的&Vec<&Inner> inners is not bounded by 'static , so the closure as a whole cannot be coerced to dyn FnMut() -> Outer , which is implicitly dyn (FnMut() -> Outer) + 'static . inners不受'static ,因此整个闭包不能被强制为dyn FnMut() -> Outer ,这隐式dyn (FnMut() -> Outer) + 'static

To fix this, you can allow the Strategy to return a function that isn't 'static , by redefining the type like so:要解决此问题,您可以通过重新定义类型来允许 Strategy 返回一个不是'static的函数,如下所示:

type Strategy = Box<
    dyn for<'a>
        Fn(&'a Vec<&'a Inner>) -> Box<dyn (FnMut() -> Outer) + 'a>
>;

Note the for<'a> .注意for<'a> This is the trait-bound syntax equivalent to declaring a function like这是等价于声明一个函数的 trait-bound 语法

fn example_strategy<'a>(&'a Vec<&'a Inner>) -> Box<dyn (FnMut() -> Outer) + 'a> {...}

where the function output has a lifetime depending on the input.其中函数输出的生命周期取决于输入。

With this change, and adding a missing mut qualifier (calling a FnMut requires mutable access to the function), your program will compile.通过此更改,并添加缺少的mut限定符(调用FnMut需要对该函数进行可变访问),您的程序将编译。

Maybe you want the FnMut() -> Outer to stay 'static ;也许您希望FnMut() -> Outer保持'static in that case, you'd need to define Strategy so that it owns the Inner s, with corresponding changes to how you call it.在这种情况下,您需要定义Strategy以便它拥有Inner s,并相应地更改您的调用方式。 But you probably don't want this since you mentioned not cloning the Inner s;但是你可能不想要这个,因为你提到不要克隆Inner I'm mentioning it for comparison.我提到它是为了比较。

type Strategy = Box<dyn Fn(Vec<Inner>) -> Box<dyn FnMut() -> Outer>>;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 由于需求冲突,无法推断出合适的生命周期 - Cannot infer an appropriate lifetime due to conflicting requirements 作为函数参数的闭包“由于需求冲突而无法推断出适当的寿命” - Closure as function parameter “cannot infer an appropriate lifetime due to conflicting requirements” "由于要求冲突,无法推断函数调用中生命周期参数 &#39;_ 的适当生命周期" - cannot infer an appropriate lifetime for lifetime parameter '_ in function call due to conflicting requirements 尝试实现迭代器:由于需求冲突而无法推断出适当的生存期 - Trying to implement an iterator: cannot infer an appropriate lifetime due to conflicting requirements 由于需求冲突,无法推断出自动强制的适当寿命 - cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements 由于需求冲突,无法为借用表达式推断出适当的生命周期 - cannot infer an appropriate lifetime for borrow expression due to conflicting requirements 由于递归结构中的冲突要求,无法推断出适当的生命周期 - Cannot infer an appropriate lifetime due to conflicting requirements in a recursive struct 由于需求冲突,无法为 autoref 推断适当的生命周期 - Cannot infer an appropriate lifetime for autoref due to conflicting requirements Rust:由于要求冲突,无法推断 autoref 的适当生命周期 - Rust: cannot infer an appropriate lifetime for autoref due to conflicting requirements 递归关闭作为函数参数“由于需求冲突而无法推断出适当的寿命” - Recursive closure as function parameter “cannot infer an appropriate lifetime due to conflicting requirements”
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM