簡體   English   中英

實現迭代器時如何返回引用?

[英]How to return a reference when implementing an iterator?

我想返回對集合中擁有的對象的引用(即Vec ),但我似乎無法獲得正確的生命周期。 這是我第一次嘗試的:

struct StringHolder {
    strings: Vec<String>,
    i: usize,
}

impl Iterator for StringHolder {
    type Item<'a> = &'a String;
    fn next(&mut self) -> Option<Self::Item> {
        if self.i >= self.strings.len() {
            None
        } else {
            self.i += 1;
            Some(&self.strings[self.i])
        }
    }
}

fn main() {
    let sh = StringHolder { strings: vec![], i: 0 };
    for string in sh {
        println!("{}", string);
    }
}

我收到一個錯誤,即generic associated types are unstable並且lifetimes do not match type in trait 我嘗試了其他一些迭代,但似乎沒有任何效果。

根據我讀過的一些內容,我認為這可能是不可能的,但是我似乎無法弄清楚Vec本身是如何做到的。 例如,我可以使用以下內容簡單地迭代底層Vec並在每次迭代時返回一個引用:


struct StringHolder {
    strings: Vec<String>,
}

impl<'a> IntoIterator for &'a StringHolder {
    type Item = &'a String;
    type IntoIter = ::std::slice::Iter<'a, String>;
    fn into_iter(self) -> Self::IntoIter {
        (&self.strings).into_iter()
    }
}

fn main() {
    let sh = StringHolder { strings: vec!["A".to_owned(), "B".to_owned()] };
    for string in &sh {
        println!("{}", string);
    }
}

所以這讓我覺得這是可能的,我只是還沒有弄清楚生命周期。 謝謝你的幫助。

Iterator trait 不包括Item的生命周期,這是您看到的錯誤之一。 另一個暗指GAT ,這是一個不穩定的 Rust 特性。 應用於此示例的 GAT 將允許您為每個對next()單獨調用綁定項目的生命周期,而不是所有項目都具有相同的生命周期。 話雖如此, Iterator trait 不太可能改變,所以這種更靈活的行為必須是一個新的 trait。

鑒於Iterator trait 的設計,你不能讓迭代器擁有它的數據並且讓它的Item成為它的引用。 只是沒有一種方式來表達一生。

為了讓項目成為引用,迭代器通常的編寫方式是讓它們持有對底層數據的引用。 這為數據提供了一個命名生命周期,可以在關聯的Item Vec有點這樣做,但它有點不同,因為Vec實際上從slice獲取它的迭代。

您的完整示例:

struct StringHolder {
    strings: Vec<String>,
}

struct StringHolderIter<'a> {
    string_holder: &'a StringHolder,
    i: usize,
}

impl<'a> Iterator for StringHolderIter<'a> {
    type Item = &'a str;
    fn next(&mut self) -> Option<Self::Item> {
        if self.i >= self.string_holder.strings.len() {
            None
        } else {
            self.i += 1;
            Some(&self.string_holder.strings[self.i - 1])
        }
    }
}

impl<'a> IntoIterator for &'a StringHolder {
    type Item = &'a str;
    type IntoIter = StringHolderIter<'a>;
    fn into_iter(self) -> Self::IntoIter {
        StringHolderIter {
            string_holder: self,
            i: 0,
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM