实现迭代器时如何return引用?
How to return a reference when implementing an iterator?
我想 return 对集合中拥有的对象的引用(即 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
和 return 每次迭代的引用:
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
特征不包括 Item
的生命周期,这是您看到的错误之一。另一个暗示 GATs 这是一个不稳定的 Rust 特性。应用于此示例的 GAT 可让您将每个单独调用的项的生命周期绑定到 next()
,而不是所有项都具有相同的生命周期。话虽如此,Iterator
特性不太可能改变,因此这种更灵活的行为必须是一个新特性。
考虑到 Iterator
特征的设计,你不能让迭代器拥有它的数据 并且 有它的 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,
}
}
}
我想 return 对集合中拥有的对象的引用(即 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
和 return 每次迭代的引用:
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
特征不包括 Item
的生命周期,这是您看到的错误之一。另一个暗示 GATs 这是一个不稳定的 Rust 特性。应用于此示例的 GAT 可让您将每个单独调用的项的生命周期绑定到 next()
,而不是所有项都具有相同的生命周期。话虽如此,Iterator
特性不太可能改变,因此这种更灵活的行为必须是一个新特性。
考虑到 Iterator
特征的设计,你不能让迭代器拥有它的数据 并且 有它的 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,
}
}
}