例如,我正在創建一個計算圖,這是一個將方程建模爲圖的程序,因此可以區分它們。我已經重載了運算符,因此添加圖形節點會創建新的圖形節點。但是,我發現自己正在與借閱檢查員作鬥爭。下面的代碼:如何超載爲Rust中的計算圖節點添加
use std::ops::Add;
#[derive(Debug)]
pub enum Expr<'a> {
Constant(f32),
// ^^^--this is a simplified version. In the real version,
// Constant holds large matrices and I would like to
// avoid copying it.
Add(&'a Node<'a>, &'a Node<'a>),
}
#[derive(Debug)]
pub struct Node<'a> {
pub body: Expr<'a>
}
impl<'a> Add for &'a Node<'a> {
type Output = Node<'a>;
fn add(self, other: &'a Node<'a>) -> Node<'a> {
Node { body: Expr::Add(self, other) }
}
}
fn main() {
let a = Node { body: Expr::Constant(1.) };
let f: Node = &(&a + &a) + &a;
println!("f: {:#?}", f);
}
正如你所看到的,+
需要採取兩種graph::Node
結構引用,並返回一個graph::Node
結構。
error: borrowed value does not live long enough
--> src/main.rs:25:20
|
25 | let f: Node = &(&a + &a) + &a;
| ^^^^^^^^^ - temporary value only lives until here
| |
| temporary value created here
26 | }
| - temporary value needs to live until here
|
= note: consider using a `let` binding to increase its lifetime
我使用的引用,因爲我想避免複製Node
結構:由於&(&a + &a)
被創建,並在同一行死了,我得到這個錯誤。這裏的代碼略有簡化;在我正在使用的版本中,這些可以保存大量數據。
我試過靜態引用和Rc
指針,並沒有成功。當我嘗試使用Rc
指針,編譯器抱怨超載Add
:
error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
--> function.rs:86:1
|
86 | impl Add for Rc<Function> {
|^impl doesn't use types inside crate
|
= note: the impl does not reference any types defined in this crate
目前我只是定義每個操作這實在是凌亂的新變量:
let f1 = &a + &a;
...
let f = &a + f1
什麼是理想的是如果我可以完全避免使用引用(這會使代碼更清晰)。至少,我需要通過添加現有節點來生成新節點的方法。
爲什麼不只是做了錯誤消息告訴您,並使用'let'結合? '讓f =&a +&a;讓f2 =&f +&a;'。爲什麼你首先存儲對'Node's的引用,而不是直接存儲它們?爲什麼不爲不引用實現'Add'? – Shepmaster
感謝@Shepmaster的建議。所以我正在使用'f1 = ...; f2 = ...'。當你處理一個複雜的大方程時,它會使代碼難於閱讀。存儲引用的原因是使用add-for非引用需要一個副本,並且對性能有問題(我簡化了代碼,但在實際版本中,圖節點可以包含大型矩陣)。 – ethanabrooks
使用Rc時出了什麼問題? –