[英]Iterator returning items by reference, lifetime issue
我有一個終身問題,我正在嘗試實現一個通過引用返回其項目的迭代器,這是代碼:
struct Foo {
d: [u8; 42],
pos: usize
}
impl<'a> Iterator<&'a u8> for Foo {
fn next<'a>(&'a mut self) -> Option<&'a u8> {
let r = self.d.get(self.pos);
if r.is_some() {
self.pos += 1;
}
r
}
}
fn main() {
let mut x = Foo {
d: [1; 42],
pos: 0
};
for i in x {
println!("{}", i);
}
}
但是這段代碼沒有正確編譯,我遇到了一個與參數生命周期相關的問題,這是相應的錯誤:
$ rustc test.rs
test.rs:8:5: 14:6 error: method `next` has an incompatible type for trait: expected concrete lifetime, but found bound lifetime parameter
test.rs:8 fn next<'a>(&'a mut self) -> Option<&'a u8> {
test.rs:9 let r = self.d.get(self.pos);
test.rs:10 if r.is_some() {
test.rs:11 self.pos += 1;
test.rs:12 }
test.rs:13 r
...
test.rs:8:49: 14:6 note: expected concrete lifetime is the lifetime 'a as defined on the block at 8:48
test.rs:8 fn next<'a>(&'a mut self) -> Option<&'a u8> {
test.rs:9 let r = self.d.get(self.pos);
test.rs:10 if r.is_some() {
test.rs:11 self.pos += 1;
test.rs:12 }
test.rs:13 r
...
error: aborting due to previous error
有人知道如何解決這個問題並仍然通過引用返回項目嗎?
至少這條消息是什么意思:預期的具體生命周期,但發現綁定的生命周期參數?
注意所使用的 Rust 版本:在編寫此問題和答案時,
Iterator
trait 使用泛型; 它已更改為使用關聯類型,現在定義如下:pub trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; … }
所以這里顯示的不正確的實現是這樣的:
impl<'a> Iterator for Foo { type Item = &'a u8; fn next<'a>(&'a mut self) -> Option<&'a u8>; }
實際上,這沒有任何影響; 只是
A
變成了Self::Item
。
Iterator
trait 的定義是這樣的:
pub trait Iterator<A> {
fn next(&mut self) -> Option<A>;
…
}
請注意: fn next(&mut self) -> Option<A>
。
這是你所擁有的:
impl<'a> Iterator<&'a u8> for Foo {
fn next<'a>(&'a mut self) -> Option<&'a u8>;
}
請注意: fn next<'a>(&'a mut self) -> Option<&'a u8>
。
這里有幾個問題:
您引入了一個新的通用參數<'a>
,它不應該在那里。 為方便起見並強調這里發生的事情,我將在 impl 塊 ρ₀ 上定義的'a
和在方法 ρ₁ 上定義的'a
配音。 她們不一樣。
&mut self
的生命周期&mut self
trait 的生命周期不同。
返回類型的生命周期與 trait 不同:其中A
是&'ρ₀ u8
,返回類型用於代替A
&'ρ₁ u8
。 它預期的具體壽命為 ρ₀,但結果卻是壽命 ρ₁。 (我不確定“綁定”位的確切含義,所以我會保持沉默,以免我錯了。)
這就是它的含義:您無法將正在迭代的對象的生命周期連接到&mut self
。 相反,它必須綁定到您正在為其實現特征的類型中的某些內容。 舉個例子,迭代切片中的項目是通過創建一個連接到基本切片的新迭代器對象來完成的, impl<'a, T> Iterator<&'a T> for Items<'a, T>
。 換句話說,迭代特征的設計方式不是,如果您正在生成引用,則返回self
內部的某些內容,而是返回您引用的另一個對象內部的某些內容。
對於您的特定的,大概是簡單的示例,您應該停止產生引用,或者更改它,以便您的迭代器對象不包含您正在迭代的數據——讓它只包含對它的引用,例如&'a [T]
甚至像Items<'a, T>
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.