Rust 如何实现产生可变引用的迭代器
我正在尝试实现一个简单的查找迭代器: LookupIterMut选项的发布结构LookupIterMut迭代器{ 如果self.i>=self.index.len(){ 没有一个 }否则{ 使用index=self.index[self.i]; 自我评价i+=1; Some(&mut self.data[index])//此处出错 } } } 其思想是允许调用者连续可变地访问内部存储器。但是,由于需求冲突,我得到了错误Rust 如何实现产生可变引用的迭代器,rust,Rust,我正在尝试实现一个简单的查找迭代器: LookupIterMut选项的发布结构LookupIterMut迭代器{ 如果self.i>=self.index.len(){ 没有一个 }否则{ 使用index=self.index[self.i]; 自我评价i+=1; Some(&mut self.data[index])//此处出错 } } } 其思想是允许调用者连续可变地访问内部存储器。但是,由于需求冲突,我得到了错误无法为函数调用中的生存期参数推断适当的生存期 据我所知,我必须将函数签名更改
无法为函数调用中的生存期参数推断适当的生存期
据我所知,我必须将函数签名更改为next(&'a mut self)->…
,但这将不再是迭代器
我还发现,我可以简单地使用原始指针,尽管我不确定这是否适合这里:
/。。。
类型项=*mut D;
// ...
感谢您的帮助您的代码无效,因为您试图以相同的生存期将多个可变引用返回到同一个片段'a
要使这样的事情起作用,您需要为每个返回的项
使用不同的生存期,这样您就不会持有对同一个切片的两个可变引用。您目前无法执行此操作,因为它需要泛型关联类型:
type Item<'item> = &'item mut D; // Does not work today
请注意,如果一个索引超出范围,您的代码将死机。使用safe
提醒:在任何时候,对同一基础值有两个可访问的可变引用都是不合理的
问题的关键在于,语言无法保证代码遵守上述规则,如果索引包含任何重复项,那么实现的迭代器将允许同时获得对切片中相同项的两个可变引用,这是不合理的
如果语言本身无法提供担保,则您需要找到替代方法,或者进行尽职调查,然后使用不安全的
在这种情况下,在:
impl{
发布fn新(数据:&'a mut[D],索引:&'a[usize])->Self{
let set:HashSet=index.iter().copied().collect();
断言!(index.len()==set.len(),“重复索引!”);
自{数据,索引,i:0}
}
}
恳求{
类型项=&'a mut D;
fn下一步(&mut self)->选项{
如果self.i>=self.index.len(){
没有一个
}否则{
设index=self.index[self.i];
断言!(索引
就性能而言,在构造函数中构造HashSet
是相当不令人满意的,但通常不能真正避免。例如,如果保证对索引进行排序,则可以在不分配的情况下执行检查。我还简化了下一步的方法。
mod my_mod {
pub struct LookupIterMut<'a, D> {
data: &'a mut [D],
indices: &'a [usize],
i: usize,
}
impl<'a, D> LookupIterMut<'a, D> {
pub fn new(data: &'a mut [D], indices: &'a [usize]) -> Result<Self, ()> {
let mut uniq = std::collections::HashSet::new();
let all_distinct = indices.iter().all(move |&x| uniq.insert(x));
if all_distinct {
Ok(LookupIterMut {
data,
indices,
i: 0,
})
} else {
Err(())
}
}
}
impl<'a, D> Iterator for LookupIterMut<'a, D> {
type Item = &'a mut D;
fn next(&mut self) -> Option<Self::Item> {
self.indices.get(self.i).map(|&index| {
self.i += 1;
unsafe { std::mem::transmute(&mut self.data[index]) }
})
}
}
}
impl<'a, D> LookupIterMut<'a, D> {
pub fn new(data: &'a mut [D], indices: &'a [usize]) -> Self {
let set: HashSet<usize> = indices.iter().copied().collect();
assert!(indices.len() == set.len(), "Duplicate indices!");
Self { data, indices, i: 0 }
}
}
impl<'a, D> Iterator for LookupIterMut<'a, D> {
type Item = &'a mut D;
fn next(&mut self) -> Option<Self::Item> {
if self.i >= self.indices.len() {
None
} else {
let index = self.indices[self.i];
assert!(index < self.data.len());
self.i += 1;
// Safety:
// - index is guaranteed to be within bounds.
// - indices is guaranteed not to contain duplicates.
Some(unsafe { &mut *self.data.as_mut_ptr().offset(index as isize) })
}
}
}