[英]Communicating Rust Lifetimes for Type Parameters
我正在研究一個簡單的復數示例,並嘗試按如下方式實現 ref-value/value-ref 操作:
use std::ops::*;
#[derive(Clone, PartialEq)]
pub struct Complex<T: Sized + Clone> {
pub re: T,
pub im: T,
}
// Ref-Ref Multiplication
impl<'a, 'b, T: Sized + Clone> Mul<&'b Complex<T>> for &'a Complex<T>
where
T: Add<T, Output = T>,
T: Sub<T, Output = T>,
&'a T: Add<&'b T, Output = T>,
&'a T: Mul<&'b T, Output = T>,
&'a T: Sub<&'b T, Output = T>,
{
type Output = Complex<T>;
fn mul(self, rhs: &'b Complex<T>) -> Complex<T> {
panic!("// Details irrelevant")
}
}
// Ref-Value Multiplication
impl<'a, 'b, T: Sized + Clone> Mul<Complex<T>> for &'a Complex<T>
where
T: 'static,
T: Add<T, Output = T>,
T: Sub<T, Output = T>,
&'a T: Add<&'b T, Output = T>,
&'a T: Mul<&'b T, Output = T>,
&'a T: Sub<&'b T, Output = T>,
{
type Output = Complex<T>;
fn mul(self, rhs: Complex<T>) -> Complex<T> {
let t = &rhs;
self.mul(t)
}
}
ref-ref 實現有效,據我所知,它接受兩個不同生命周期的引用,並返回一個復雜的值類型。 參考值部分是我遇到問題的地方; 當我編譯時,錯誤是rhs
壽命不夠長。 我相信我已經知道為什么會這樣了,那就是當返回值時 T 可以持有對 rhs 的引用(直接或間接),因此rhs
超出范圍,但T
仍然可以持有對它的引用。
我的問題是如何傳達T
不會以某種形狀或形式引用rhs
。
關於我迄今為止嘗試過或看過的事情的一些說明:
T
持有的引用將至少與T
一樣長,所以我認為我需要更多“至多”之類的東西。正如 Peter Hall 在評論中所建議的,最簡單的解決方案是為您的復雜類型派生Copy
,並實現對值的操作。 對於 ref-ref 實現和 ref-val 實現,您可以簡單地取消引用引用並使用 val-val 實現。
如果你想讓你開始的方法起作用,你需要更高等級的特征邊界:
use std::ops::*;
#[derive(Clone, PartialEq)]
pub struct Complex<T: Clone> {
pub re: T,
pub im: T,
}
// Ref-Ref Multiplication
impl<'a, 'b, T: Clone> Mul<&'b Complex<T>> for &'a Complex<T>
where
T: Add<T, Output = T>,
T: Sub<T, Output = T>,
&'a T: Add<&'b T, Output = T>,
&'a T: Mul<&'b T, Output = T>,
&'a T: Sub<&'b T, Output = T>,
{
type Output = Complex<T>;
fn mul(self, rhs: &'b Complex<T>) -> Complex<T> {
Complex {
re: &self.re * &rhs.re - &self.im * &rhs.im,
im: &self.re * &rhs.im + &self.im * &rhs.re,
}
}
}
// Ref-Value Multiplication
impl<'a, T: Clone> Mul<Complex<T>> for &'a Complex<T>
where
T: Add<T, Output = T>,
T: Sub<T, Output = T>,
&'a T: for<'b> Add<&'b T, Output = T>,
&'a T: for<'b> Mul<&'b T, Output = T>,
&'a T: for<'b> Sub<&'b T, Output = T>,
{
type Output = Complex<T>;
fn mul(self, rhs: Complex<T>) -> Complex<T> {
let t = &rhs;
self.mul(t)
}
}
在您的版本中,引用值實現中的生命周期'b
由特征的用戶選擇。 由於用戶可以為'b
使用任何生命周期,因此rhs
需要靜態生命周期才能使您的代碼有效。 相反,您想要的是*'a T
滿足任何給定生命周期'b
的給定特征邊界,這正是 HRTB 的用途。
為第二個實現編寫 trait bound 的另一種不太重復的方法是:
impl<'a, T: Clone> Mul<Complex<T>> for &'a Complex<T>
where
Self: for<'b> Mul<&'b Complex<T>, Output = Complex<T>>,
{
type Output = Complex<T>;
fn mul(self, rhs: Complex<T>) -> Complex<T> {
self.mul(&rhs)
}
}
內置數字類型使用宏實現這些排列。 手動完成,我將從您將兩個值相乘而不是任何引用的情況開始,並確保您的Complex
結構是Copy
:
impl<T: Copy> Mul<Complex<T>> for Complex<T>
where
T: Add<T, Output = T>,
T: Sub<T, Output = T>,
T: Mul<T, Output = T>,
{
type Output = Complex<T>;
fn mul(self, rhs: Complex<T>) -> Complex<T> {
unimplemented!()
}
}
請注意,您不需要對&T
任何約束 - 無論如何您都無法返回對T
引用,因此您將不得不復制它們,這就是我指定T: Copy
。
其余的實現現在很簡單,可以委托給最簡單的情況:
impl<'a, T: Copy> Mul<Complex<T>> for &'a Complex<T>
where
T: Add<T, Output = T>,
T: Sub<T, Output = T>,
T: Mul<T, Output = T>,
{
type Output = Complex<T>;
fn mul(self, rhs: Complex<T>) -> Complex<T> {
(*self).mul(rhs)
}
}
impl<'a, T: Copy> Mul<&'a Complex<T>> for Complex<T>
where
T: Add<T, Output = T>,
T: Sub<T, Output = T>,
T: Mul<T, Output = T>,
{
type Output = Complex<T>;
fn mul(self, rhs: &'a Complex<T>) -> Complex<T> {
self.mul(*rhs)
}
}
impl<'a, 'b, T: Copy> Mul<&'a Complex<T>> for &'b Complex<T>
where
T: Add<T, Output = T>,
T: Sub<T, Output = T>,
T: Mul<T, Output = T>,
{
type Output = Complex<T>;
fn mul(self, rhs: &'a Complex<T>) -> Complex<T> {
(*self).mul(*rhs)
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.