Rust Vec到切片会话的显式生存期

Rust Vec到切片会话的显式生存期,rust,Rust,我希望对列表中的更改进行回调,因此我创建了一个简单的示例: struct Foo; struct FooList { list: Vec<Foo>, on_change_cb: Vec<Box<FnMut(& mut [Foo])>>, } impl FooList { /* pub fn register_on_change_cb2<F>(&mut self, cb: F) where F: FnMu

我希望对列表中的更改进行回调,因此我创建了一个简单的示例:

struct Foo;

struct FooList {
    list: Vec<Foo>,
    on_change_cb: Vec<Box<FnMut(& mut [Foo])>>,
}

impl FooList {
 /*
    pub fn register_on_change_cb2<F>(&mut self, cb: F) where F: FnMut(&mut [Foo]) {
        self.on_change_cb.push(Box::new(cb));
    }*/

    pub fn register_on_change_cb(&mut self, cb: Box<FnMut(&mut [Foo])>) {
        self.on_change_cb.push(cb);
    }

    pub fn push(&mut self, foo: Foo) {
        self.list.push(foo);
        self.on_change();
    }


    fn on_change(&mut self) {
        for cb in &mut self.on_change_cb {
            cb(&mut self.list);
        }
    }
}
structfoo;
结构傻瓜{
名单:Vec,,
关于变更,cb:Vec,
}
傻瓜{
/*
发布fn寄存器\u on\u change\u cb2(&mut self,cb:F),其中F:FnMut(&mut[Foo]){
自动更改cb推送(Box::new(cb));
}*/
发布fn寄存器打开更改cb(&mut self,cb:Box){
自换式cb推送(cb);
}
pub fn push(&mut self,foo:foo){
self.list.push(foo);
self.on_change();
}
fn on_更改(&mut self){
对于cb in和mut self.on_change_cb{
cb(和多个自身列表);
}
}
}
  • 这里我没有给编译器任何关于生命周期的明确提示:
    Vec
    ,那么编译器在这里使用什么生命周期呢?如果我这样更改代码:

    struct FooList<'a> {
        list: Vec<Foo>,
        on_change_cb: Vec<Box<FnMut(&'a mut [Foo])>>,
    }
    impl<'a> FooList<'a> {
    
    struct-woulist>,
    }
    恳求{
    
    我得到一个编译时错误:

    错误[E0495]:无法推断借用的适当生存期 由于相互冲突的要求而导致的表达

  • 如何以某种方式显式设置生命周期,使回调的
    &mut[Foo]
    的生命周期小于但不等于整个
    傻瓜对象的生命周期

  • 我已对更改cb2上的注册发表了评论,我想允许调用更改cb上的注册,而不使用新的,但失败。如果取消注释更改cb2上的注册,您将得到错误:

    错误[E0310]:参数类型
    F
    可能寿命不够长

    如何在不要求回调的
    静态
    生存期的情况下修复此错误?我只想调用
    Box::new


  • 我将试着回答你的问题1和3,因为问题2要么是多余的,要么是与其他问题正交的,我不知道你真正想通过它实现什么。也许它应该有一个自己的问题

  • 如果您有一个引用的函数,但它不需要任何有关引用的生存期信息,那么它必须能够接受anylife的引用。下面是它的显式语法(这是编译器从您编写的代码中推断的):

    这类似于:“对于每个
    傻瓜列表
    对象,都有一个生存期
    'a
    ,因此
    傻瓜列表
    中的每个回调都只包含至少生存了
    'a
    的引用。”这种解释可能会使编写
    register\u on\u change\u cb2
    的原型更容易:它接受一个回调,该回调也只包含至少存在
    'a
    的引用

    impl<'a> FooList<'a> {
        pub fn register_on_change_cb2<F>(&mut self, cb: F)
            where F: FnMut(&mut [Foo]) + 'a
        {
            self.on_change_cb.push(Box::new(cb));
        }
    
    在本例中,您不能插入捕获
    短命的
    的闭包,因为它不超过(推断的)生存期
    'a
    。但您可以插入捕获
    长寿命的
    的闭包,因为编译器可以推断满足这两个约束的生存期
    'a


    • 'a
      必须比
      列表
      更长寿,因为
      列表
      属于
      愚人类型我将尝试回答你的问题1和3,因为问题2要么是多余的,要么是与其他问题正交的,我无法告诉你真正想要通过它实现什么。也许它值得一个自己的问题

    • 如果您有一个引用的函数,但它不需要任何有关引用的生存期信息,那么它必须能够接受anylife的引用。下面是它的显式语法(这是编译器从您编写的代码中推断的):

      这类似于:“对于每个
      傻瓜列表
      对象,都有一个生存期
      'a
      ,因此
      傻瓜列表
      中的每个回调都只包含至少生存了
      'a
      的引用。”这种解释可能会使编写
      register\u on\u change\u cb2
      的原型更容易:它接受一个回调,该回调也只包含至少存在
      'a
      的引用

      impl<'a> FooList<'a> {
          pub fn register_on_change_cb2<F>(&mut self, cb: F)
              where F: FnMut(&mut [Foo]) + 'a
          {
              self.on_change_cb.push(Box::new(cb));
          }
      
      在本例中,您不能插入捕获
      短命的
      的闭包,因为它不超过(推断的)生存期
      'a
      。但您可以插入捕获
      长寿命的
      的闭包,因为编译器可以推断满足这两个约束的生存期
      'a


      • 'a
        必须比
        列表
        更长寿,因为
        列表
        属于
        傻瓜类型,请只拥有一个。@Shepmaster实际上,我认为这些问题是同一事物的不同方面,如何
        Vec
        +slice+
        FnMut
        合作,这就是为什么我把这些问题合并成一个问题,请只拥有一个。@Shepmaster Actuallly,我认为这些问题是同一事物的不同方面,如何
        Vec
        +slice+
        FnMut
        合作,这就是为什么我把这些问题组合成一个汉克,但为什么生命在
        3
        中很重要?我把
        cb
        放进
        框中,然后我通过值得到它?@user1244932
        Boxe关于它包含的引用的知识。我添加了一个示例,说明
        'a
        生命周期如何确保
        cb
        只包含比
        傻瓜
        生命周期长的引用。谢谢,但是为什么在
        3
        中生命周期很重要?我将
        cb
        放入
        框中,然后通过值得到它?@user1244932
        >我添加了一个例子,说明
        'a
        生存期如何确保
        cb
        只包含比
        傻瓜
        寿命长的引用。
        impl<'a> FooList<'a> {
            pub fn register_on_change_cb2<F>(&mut self, cb: F)
                where F: FnMut(&mut [Foo]) + 'a
            {
                self.on_change_cb.push(Box::new(cb));
            }
        
        let longlived = String::from("hello");
        let mut list = FooList {
            list: Vec::new(),
            on_change_cb: Vec::new(),
        };
        list.register_on_change_cb2(|_| println!("{}", longlived)); // ok
        
        let shortlived = String::from("hello");
        list.register_on_change_cb2(|_| println!("{}", shortlived)); // `shortlived` does not live long enough
        
        list.push(Foo);
        
            pub fn register_on_change_cb2<F>(&mut self, cb: F)
                where F: FnMut(&mut [Foo]) + 'static