当前位置: 首页 > 知识库问答 >
问题:

函数引用:预期绑定生存期参数,找到具体生存期[E0271]

谷梁卓
2023-03-14

关于这个主题已经有很多线程,但是我看不出讨论的问题是否适用于我的特定问题。

我有一个存储名称回调函数的结构。简而言之,问题是这样的:

pub struct Command<'a> {
    name: &'a str,
    callback: &'a Fn(&[&str]) -> ()
}

impl <'a> Command<'a> {
    pub fn new(name: &'a str, callback: &'a Fn(&[&str]) -> ()) -> Command<'a> {
        Command {
            name: name,
            callback: callback
        }
    }
}

我想做的是存储一个与名称相关联的回调函数(将来可能会有更多内容)。

但当我尝试这样使用这段代码时:

fn main() {
    let play_callback = |args| {
        println!("Playing something.");
        for arg in args {
            println!("{}", arg);
        }
    };
    let play_command = Command::new("play", &play_callback);
}

我得到以下错误消息:

src/main.rs:22:42: 22:56 error: type mismatch resolving `for<'r, 'r> <[closure@src/main.rs:16:22: 21:3] as std::ops::FnOnce<(&'r [&'r str],)>>::Output == ()`:
 expected bound lifetime parameter ,
    found concrete lifetime [E0271]
src/main.rs:22  let play_command = Command::new("play", &play_callback);
                                                        ^~~~~~~~~~~~~~

我试着像这样内联闭包

fn main() {
    let play_command = Command::new("play", &|args| {
        println!("Playing something.");
        for arg in args {
            println!("{}", arg);
        }
    });
}

但是我又犯了一个错误

src/main.rs:16:47: 21:7 error: borrowed value does not live long enough

我相信我明白为什么我会这样。

在切换到一个函数引用以存储在我的命令结构中之前,我尝试使用一个通用类型参数,但是当我想初始化命令对象的HashSet时,如下所示:

let mut commands: HashSet<Command> = HashSet::new();

编译器希望我指定泛型参数,我认为我不能这样做,因为这意味着我只能在所有命令对象中存储相同的闭包。

所以我的问题是:我怎样才能实现我想要的,什么是最好的方式(为什么)?


共有2个答案

步兴德
2023-03-14

您是否尝试过指定args的类型?以下内容为我编写:

fn main() {
    let play_callback = |args: &[&str]| {
        println!("Playing something.");
        for arg in args {
            println!("{}", arg);
        }
    };
    let play_command = Command::new("play", &play_callback);
}

不过,我不知道为什么没有推断出来。

贺雪松
2023-03-14

简单的解决方法(由ljedrz)是args:

当您使用对某个trait的引用作为函数参数时,它将被视为trait对象。在这种情况下,

trait对象的一个简单类比是用其他语言实现接口的对象。

然而,生命周期对trait对象的工作方式有点不同。你可以认为它们与通常的所有权流“分离”。如果我们在示例中注释Fntrait对象生存期'c,我们将得到以下代码:

pub struct Command<'a> {
    name: &'a str,
    callback: &'a for<'c> Fn(&'c [&'c str]) -> ()
}

impl <'a> Command<'a> {
    pub fn new<'r>(name: &'r str, callback: &'r for<'c> Fn(&'c [&'c str]) -> ()) -> Command<'r> {
        Command {
            name: name,
            callback: callback
        }
    }
}

fn main() {
    let play_callback = |args: &[&str]| {
        println!("Playing something.");
        for arg in args {
            println!("{}", arg);
        }
    };
    let play_command = Command::new("play", &play_callback);
}

在上面的代码中,生存期'c描述了调用回调函数的范围。

然而,上面的代码不是很实用。它将命令耦合到创建闭包的作用域(记住,trait对象引用该作用域中的闭包)。因此,您无法退出创建命令的函数,因为这会破坏闭包!

可能的解决方案是将闭包存储在堆上的框中

pub struct Command<'a> {
    name: &'a str,
    callback: Box<Fn(&[&str]) -> ()>
}

impl <'a> Command<'a> {
    pub fn new<'r>(name: &'r str, callback: Box<Fn(&[&str]) -> ()>) -> Command<'r> {
        Command {
            name: name,
            callback: callback
        }
    }
}

fn main() {
    let play_callback = |args: &[&str]| {
        println!("Playing something.");
        for arg in args {
            println!("{}", arg);
        }
    };
    let play_command = Command::new("play", Box::new(play_callback));
}

在上面的示例中,创建长方体时,闭包将移动到长方体中,并将与命令一起销毁。

 类似资料:
  • 我目前正在听这个。我试图把它缩小到一个最小的可重复的例子。 这给我留下了: 以前,我将我的存储在像这样的中 但是现在我想重构一些东西,并引入了一个结构,并将东西存储为

  • 我试图编写一个函数,使用闭包验证给定的集合。该函数获取集合的所有权,对内容进行迭代,如果没有找到无效的项,则返回集合的所有权。这就是为什么它可以这样使用(而不需要为创建一个temp):

  • 我无法计算出这段代码的生存期参数。我所尝试的一切通常都会导致编译器错误:“预期的绑定生存期参数,找到了具体的生存期”或者类似于“考虑使用所示的显式生存期参数”(所示的示例没有帮助)或“与trait不兼容的方法”。 、和都是简化版本,以尽量减少此示例。 铁锈游乐场

  • 我正在尝试在结构中存储函数: 编译器抱怨:

  • 忽视省略(elision)情况,带上生命周期的函数签名(function signature)有一些限制: 任何引用都必须拥有标注好的生命周期。 任何被返回的引用都必须有一个和输入量相同的生命周期或是静态类型(static)。 另外要注意,若会导致返回的引用指向无效数据,则返回不带输入量的引用是被禁止的。下面例子展示了一些带有生命周期的函数的有效形式: // 一个拥有生命周期 `'a` 的输入引用

  • 本文向大家介绍react生命周期函数相关面试题,主要包含被问及react生命周期函数时的应答技巧和注意事项,需要的朋友参考一下 这个问题要考察的是组件的生命周期 一、 初始化阶段: Constructor初始化状态 componentWillMount:组件即将被装载、渲染到页面上 render:组件在这里生成虚拟的DOM节点 componentDidMount:组件真正在被装载之后 二、 运行中