2014-09-02 13 views
2

我有2个载体(的Result s)内的一个对象。第一个矢量all_results拥有其内容,第二个矢量current_results包含引用 到all_results的内容。下面的代码如何复制参考文件? (终生问题)

struct Result { 
    val: int 
} 

struct Obj<'a> { 
    all_results: Vec<Result>, 
    current_results: Vec<&'a mut Result> 
} 

impl<'a> Obj<'a> { 
    fn change_something (&'a mut self) -> &[&'a mut Result] { 
     let mut newVec: Vec<&'a mut Result> = Vec::new(); 
     for item in self.current_results.mut_iter() { 
      // type of item is &mut &'a mut Result 
      item.val += 1; 
      //need to create valid reference here 
      if (item.val == 1) { 
       newVec.push(*item); //dereferenced item is now &'a mut Result 
      } 
     } 
     self.current_results = newVec; 
     self.current_results.as_slice() 
    } 
} 

fn main() { 
    let a = Result { val: 0 }; 
    let b = Result { val: 1 }; 
    let mut obj = Obj { all_results: vec![], current_results: vec![] }; 
    obj.all_results.push(a); 
    obj.all_results.push(b); 
    obj.change_something(); 
} 

基本上我试图做的是要经过的每个条目中current_results,修改它们指向Result,然后过滤基于一些标准进行评审。 但是,我不能使用相同的参考,因为编译器抱怨item比其范围允许的时间长。

iter_lifetime2.rs:16:29: 16:34 error: lifetime of `item` is too short to guarantee its contents can be safely reborrowed 
iter_lifetime2.rs:16     newVec.push(*item); 
               ^~~~~ 
iter_lifetime2.rs:11:61: 21:6 note: `item` would have to be valid for the lifetime 'a as defined on the block at 11:60... 
iter_lifetime2.rs:11  fn change_something (&'a mut self) -> &[&'a mut Result] { 
iter_lifetime2.rs:12   let mut newVec: Vec<&'a mut Result> = Vec::new(); 
iter_lifetime2.rs:13   for item in self.current_results.mut_iter() { 
iter_lifetime2.rs:14    item.val += 1; 
iter_lifetime2.rs:15    if (item.val == 1) { 
iter_lifetime2.rs:16     newVec.push(*item); 
        ... 
iter_lifetime2.rs:13:9: 19:13 note: ...but `item` is only valid for the expression at 13:8 
iter_lifetime2.rs:13   for item in self.current_results.mut_iter() { 
iter_lifetime2.rs:14    item.val += 1; 
iter_lifetime2.rs:15    if (item.val == 1) { 
iter_lifetime2.rs:16     newVec.push(*item); 
iter_lifetime2.rs:17    } 
iter_lifetime2.rs:18   } 

我试过几个变种,如:

for item in self.current_results.mut_iter() { 
    let p: &'a mut Result = *item; 
    item.val += 1; 
    if (item.val == 1) { 
     newVec.push(p); 
    } 
} 

,但我得到关于item

一生这里是我的向量的基本指针图相同的错误,希望这是我的意图更清楚。谢谢!

pointer diagram

问题:

有没有一种方法来创建从现有的参考参考?感觉就像我应该能够生成另一个指针,指向'a终生时间,并指向'a终生时间的对象。还是有更好的方法来解决这样的问题?

回答

1

Vec有一个retain方法几乎做你想做的。它不允许在过滤它们之前突变元素。我们可以写我们自己的retain_mut方法。我刚刚从不可变版本复制了代码,并对其进行了修改以允许突变。

trait RetainMut<T> { 
    fn retain_mut(&mut self, f: |&mut T| -> bool); 
} 

impl<T> RetainMut<T> for Vec<T> { 
    fn retain_mut(&mut self, f: |&mut T| -> bool) { 
     let len = self.len(); 
     let mut del = 0u; 
     { 
      let v = self.as_mut_slice(); 
      for i in range(0u, len) { 
       if !f(&mut v[i]) { 
        del += 1; 
       } else if del > 0 { 
        v.swap(i-del, i); 
       } 
      } 
     } 
     if del > 0 { 
      self.truncate(len - del); 
     } 
    } 
} 

然后你的代码看起来像这样

struct Result { 
    val: int 
} 

struct Obj<'a> { 
    all_results: Vec<Result>, 
    current_results: Vec<&'a mut Result> 
} 

impl<'a> Obj<'a> { 
    fn change_something (&mut self) -> &[&mut Result] { 
     self.current_results.retain_mut(|result| { 
      result.val += 1; 
      result.val == 1 
     }); 
     self.current_results.as_slice() 
    } 
} 
+0

感谢。虽然我更期待理解而不是解决方案,因为我相信我将来会遇到类似的情况。欣赏单通解决方案。我会编辑我的问题。 – 2014-09-02 11:18:45