2014-09-02 41 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