2017-05-19 56 views
1

有一些小例子,库代码我想用:如何解决这个“活不够长”?

struct MyR<'a> { 
    x: &'a str, 
} 

struct T { 
    x: &'static str, 
} 

impl T { 
    fn bar<'a>(&'a self) -> MyR { 
     MyR { x: self.x } 
    } 
} 

以下是我的代码:

trait A<R, F: FnMut(&R)> { 
    fn foo(&mut self, callback: &mut F); 
} 

impl<'a, F> A<MyR<'a>, F> for T 
    where F: FnMut(&MyR<'a>) 
{ 
    fn foo(&mut self, callback: &mut F) { 
     let t = T { x: "l" }; 
     let r = t.bar(); // t does not live long enough (for 'a) 
     callback(&r); 
     println!("abc"); 
    } 
} 

fn test() { 
    let mut t = T { x: "l" }; 
    let mut i = 1; 
    t.foo(&mut |x| { i += x.x.len(); }); 
} 

我想提出由回调参数化的性状,但我努力做对了。如果我不使用一个特点,它工作得很好:

impl T { 
    fn foo<F: FnMut(&MyR)>(&mut self, callback: &'a mut F) { 
     let t = T { x: "l" }; 
     let r = t.bar(); 
     callback(&r); 
     println!("abc"); 
    } 
} 

但我不能这样做:

impl T { 
    fn foo<'a, F: FnMut(&MyR<'a>)>(&mut self, callback: &mut F) { 
     let t = T { x: "l" }; 
     let r = t.bar(); 
     callback(&r); 
     println!("abc"); 
    } 
} 

我知道这个问题是t必须活得比'a,但我不知道限制'a,使其寿命短于t

我每晚使用rustc 1.19.0。

回答

1

读取错误消息:

  1. t不活足够长的时间 - 它的生命,直到foo函数结束。
  2. 借来的值必须是有效的一生“一 - 指定'a

    impl<'a, F> A<MyR<'a>, F> for T 
        where F: FnMut(&MyR<'a>) 
    

    这是说,对于任何可能一辈子,特质将被执行,只要F实现了FnMut特质。

这里只有一个可能方式,使这项工作 - 你必须有一个MyR是参数与'static寿命。这是唯一可以保证超过任意寿命的一生。

顺其自然MyR来自:

fn bar<'a>(&'a self) -> MyR { 
    MyR { x: self.x } 
} 

如果你回去重读The Rust Programming Language section on lifetime elision,你会认识到这一辈子规范提供了没有价值。它定义了一个生命周期,并将其与self一起使用,但它永远不会受限于任何输出生命周期。该代码是一样的:

fn bar<'a, 'b>(&'a self) -> MyR<'b> 

如果删除了一辈子,那么你就必须

fn bar(&self) -> MyR 
fn bar<'a>(&'a self) -> MyR<'a> // equivalent 

然而,这些都不是'static寿命。幸运的是,你知道这x&'static str,所以你可以反映在您的签名和代码可以编译:

fn bar(&self) -> MyR<'static> 
+0

我不能够改变的lib代码。我只能改变我的代码。我有没有办法可以制作一个抽象fn foo (&mut self,callback:&'a mut F)'的特征? – colinfang

0

花了几个小时尝试不同的方法,这似乎工作

trait A<F> { 
    fn foo(&mut self, callback: &mut F); 
} 

impl<F> A<F> for T 
    where F: FnMut(&MyR) 
{ 
    fn foo(&mut self, callback: &mut F) { 
     let t = T { x: "l" }; 
     let r = t.bar(); // t does not live long enough (for 'a) 
     callback(&r); 
     println!("abc"); 
    } 
} 

fn main() { 
    let mut t = T { x: "l" }; 
    let mut i = 1; 
    t.foo(&mut |x: &MyR| { i += x.x.len(); }); 

} 

的主要区别是:

  • 我有,它需要的任意类型的松动性状的位。
  • 因此,当我impl时,我不必指定生命期。
  • 我必须在调用函数时键入注释闭包。

Playground