2017-12-27 75 views
0

我剛開始生鏽,但不能完全把握的壽命,所以我可以通過自己解決以下問題:的結構鏽壽命引用

這個測試項目是模擬位以允許通過各種逐位跟蹤它操作,例如let newbit = oldbit1^oldbit2並在看newbit我可以告訴它後來它作爲操作數的異或操作與oldbit1oldbit2

#[derive(Copy,Clone)] 
pub enum TraceOperation { 
     AND, 
     OR, 
     XOR, 
     NOT, 
} 

#[derive(Copy,Clone)] 
pub struct TraceBit<'a> { 
     source_a: Option<&'a TraceBit<'a>>, 
     source_b: Option<&'a TraceBit<'a>>, 
     source_op: Option<TraceOperation>, 
     value: bool, 
} 

這個編譯,但我不完全理解爲什麼這樣的生命週期參數需要。我假設編譯器不能期望成員source_asource_b只要結構本身存在,因爲這可能不適用,所以需要明確的生命週期。

  • 這個假設是否正確?

而且我不完全理解爲什麼我爲什麼我寫source_a: Option<&'a TraceBit<'a>>,而不是source_a: Option<&'a TraceBit>重新指定爲引用類型,即壽命參數。

  • 什麼是第二次使用壽命?我如何大聲讀出那條線?我有: 「source_aOption類型的變量,其可以具有Some參考(即有效至少只要該結構本身和只要構件source_b)至TraceBit的實例」

我的最終問題是,我不能讓它使用重載運算符的工作:

use std::ops::BitXor; 
impl<'a> BitXor for TraceBit<'a> { 
     type Output = Self; 
     fn bitxor(self, rhs: Self) -> Self { 
       let valA: usize = if self.value { 1 } else { 0 }; 
       let valB: usize = if rhs.value { 1 } else { 0 }; 
       let val = if valA^valB != 0 { true } else { false }; 
       TraceBit { source_a: Some(&self), source_b: Some(&rhs), source_op: Some(TraceOperation::XOR), value: val } 
     } 
} 

這基本上是純粹的猜測基於BitXor documentation。因此,我試圖以非常明確的方式對兩個輸入變量執行異或運算,並創建一個新的輸入爲TraceBit,並將輸入存儲在其中作爲參考。

error[E0597]: `self` does not live long enough 
    --> libbittrace/src/lib.rs:37:30 
    | 
37 | TraceBit { source_a: Some(&self), source_b: Some(&rhs), source_op: Some(TraceOperation::XOR), value: val } 
    |        ^^^^ does not live long enough 
38 | } 
    | - borrowed value only lives until here 
    | 
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 31:1... 
    --> libbittrace/src/lib.rs:31:1 
    | 
31 |/impl<'a> BitXor for TraceBit<'a> { 
32 | | type Output = Self; 
33 | | fn bitxor(self, rhs: Self) -> Self { 
34 | | let valA: usize = if self.value { 1 } else { 0 }; 
... | 
40 | | 
41 | | } 
    | |_^ 

error[E0597]: `rhs` does not live long enough 
    --> libbittrace/src/lib.rs:37:53 
    | 
37 | TraceBit { source_a: Some(&self), source_b: Some(&rhs), source_op: Some(TraceOperation::XOR), value: val } 
    |              ^^^ does not live long enough 
38 | } 
    | - borrowed value only lives until here 
    | 
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 31:1... 
    --> libbittrace/src/lib.rs:31:1 
    | 
31 |/impl<'a> BitXor for TraceBit<'a> { 
32 | | type Output = Self; 
33 | | fn bitxor(self, rhs: Self) -> Self { 
34 | | let valA: usize = if self.value { 1 } else { 0 }; 
... | 
40 | | 
41 | | } 
    | |_^ 

error: aborting due to 2 previous errors 
  • 好像也沒什麼生活比XOR操作本身更長的時間,但我怎麼能解決這個問題?

我已經嘗試了各種解決辦法/更改代碼,但無濟於事,並以任何方式我比較想了解的問題不是猜測正確的解決方案....

回答

0

樹狀結構必須使用Box指針類型(Option<Box<TraceBit>>)。一般來說,在結構中你應該更喜歡擁有類型。

鏽的引用不僅僅是指針。它們是必須以其他地方擁有的數據的借用(編譯時讀/寫鎖)。

所以,如果你有一個TraceBit國有版本:

pub struct TraceBit { 
    source_a: Option<Box<TraceBit>>, 
} 

然後參照它的類型爲:&'a TraceBit,而是一個類型的引用不更改類型內部的外觀,所以類型source_a仍然是Box<TraceBit>。你可以不斷收到&'a TraceBit引用遞歸地一步一步:

trace_bit = trace_bit.source_a.as_ref().unwrap(); 

但有魯斯特沒有構造物,其中採取參考一樹的根突然改變了整個樹到引用的樹,所以類型你正在創建不能存在,這就是爲什麼你無法獲得正確的類型註釋。

0

可能不是傳遞引用,而應該使用包含和可複製的名稱類型。

use std::rc::Rc; 

#[derive(Debug)] 
pub enum TraceOperation { 
    AND, 
    OR, 
    XOR, 
    NOT, 
} 

#[derive(Debug)] 
pub enum BitName<T> { 
    Name(Rc<T>), 
    Combination(Rc<(TraceOperation, BitName<T>, BitName<T>)>), 
} 

impl<T> Clone for BitName<T> { 
    fn clone(&self) -> Self { 
     match self { 
      &BitName::Name(ref x) => BitName::Name(Rc::clone(x)), 
      &BitName::Combination(ref x) => BitName::Combination(Rc::clone(x)), 

     } 
    } 
} 

impl<T> From<T> for BitName<T> { 
    fn from(x:T) -> Self { 
     BitName::Name(Rc::new(x)) 
    } 
} 

impl<T> BitName<T> { 
    pub fn combine(op : TraceOperation, a : &Self, b :&Self) -> Self { 
     BitName::Combination(Rc::new((op, (*a).clone(), (*b).clone()))) 
    } 
} 

fn main() { 
    let x : BitName<String> = BitName::from(String::from("x")); 
    let y : BitName<String> = BitName::from(String::from("y")); 
    let xandy = BitName::combine(TraceOperation::AND, &x, &y); 
    println!("{:?}", xandy); 
}