[英]How to implement Iterator for boxed values?
我有一個結構,通過方法給出的數字next
的特質Iterator
:
struct Numbers{
number: usize,
count: usize
}
impl Iterator for Numbers {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if self.count > 0 {
self.count -= 1;
return Some(self.number);
}
return None;
}
}
fn main(){
let numbers = Numbers{
number: 777,
count: 10
};
for n in numbers {
println!{"{:?}", n};
}
}
使用usize
類型可以正常工作。 但是具有Box類型的相同代碼會產生編譯錯誤:
struct Numbers{
number: Box<usize>,
count: usize
}
impl Iterator for Numbers {
type Item = Box<usize>;
fn next(&mut self) -> Option<Self::Item> {
if self.count > 0 {
self.count -= 1;
return Some(self.number);
}
return None;
}
}
fn main(){
let numbers = Numbers{
number: Box::new(777),
count: 10
};
for n in numbers {
println!{"{:?}", n};
}
}
./numbers.rs:12:25:12:29錯誤:無法移出借用的內容
./numbers.rs:12返回Some(self.number);
如何正確實現帶框值的迭代器?
這歸結於Rust的所有權模型以及復制和移動語義之間的區別。 Box<T>
具有移動語義,未實現Copy
,因此return Some(self.number);
會移動self.number
,獲得它的所有權; 但這是不允許的,因為這將需要消耗self
,而self
只能通過可變引用來獲取。
您有幾種選擇(在這里我寫“具有移動語義的對象”,在這種情況下,我的意思是self.number
):
不要使用移動語義返回對象,使用復制語義引用返回其他內容,例如使用引用而不是裝箱的值(返回引用將要求迭代器對象與要迭代的對象不同,以便您可以編寫Item
的有效期;因此,不適用於您的特定用例)或未裝箱的編號。
構造一個新值以基於具有移動語義的對象返回:
impl Iterator for Numbers { type Item = Box<usize>; fn next(&mut self) -> Option<Self::Item> { if self.count > 0 { self.count -= 1; Some(Box::new(self.number)) } else { None } } }
使用移動語義克隆對象(實際上,這是第二種選擇的簡化形式):
impl Iterator for Numbers { type Item = Box<usize>; fn next(&mut self) -> Option<Self::Item> { if self.count > 0 { self.count -= 1; Some(self.number.clone()) } else { None } } }
構造一個新值,以移動語義代替對象:
use std::mem; impl Iterator for Numbers { type Item = Box<usize>; fn next(&mut self) -> Option<Self::Item> { if self.count > 0 { self.count -= 1; let number = mem::replace(&mut self.number, Box::new(0)); // self.number now contains 0 Some(number) } else { None } } }
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.