2017-12-27 76 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); 
}