我刚开始使用Rust,但不能完全掌握生命周期,所以我可以自己解决以下问题:
该测试项目是关于模拟一点以允许通过各种按位操作来跟踪它,例如, let newbit = oldbit1 ^ oldbit2
并查看newbit
之后我可以告诉它来自以oldbit1
和oldbit2
为操作数的XOR操作。
#[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_a
和source_b
只要结构本身存在,因为这可能不成立,因此需要明确的生命周期。
此外,我还不完全理解为什么必须为参考类型重新指定生命周期参数,即为什么我必须写source_a: Option<&'a TraceBit<'a>>
而不是source_a: Option<&'a TraceBit>
。
source_a
是Option
类型的变量,可能有Some
引用(至少与结构本身一样有效,只要成员source_b
)到TraceBit
&#34; 我的最后一个问题是我无法使用重载运算符使其工作:
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的纯粹猜测。所以我尝试以非常明确的方式对两个输入变量执行xor操作,并创建一个新的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
我已尝试过各种变通方法/代码更改,但无论如何我都不喜欢理解这个问题,而不是猜测正确的解决方案....
答案 0 :(得分:0)
树状结构必须使用Box
指针类型(Option<Box<TraceBit>>
)。通常,在结构中,您应该更喜欢拥有类型。
Rust引用不仅仅是指针。它们是借用(编译时读/写锁)数据,必须存在于其他地方。
因此,如果您拥有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();
但在Rust中没有构造,引用树的根突然将整个树变为引用树,因此您创建的类型不可能存在,这就是为什么您无法获取类型注释正确。
答案 1 :(得分: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);
}