rust - 实现 IntoIterator 以迭代内部集合时的生命周期冲突
问题描述
我有以下结构:
pub struct Data<T, IDX: From<usize>> {
inner: Vec<T>,
_idx_marker: std::marker::PhantomData<IDX>,
// other data...
}
我想实现IntoIterator
for &Data
and &mut Data
,它迭代一些内部集合。此外,迭代器不仅返回当前条目,还返回一个额外的 generic IDX
。
在&Data
一切正常的情况下。但是在实现IntoIterator
时&mut Data
我遇到了以下问题:
// impl<'a, T, IDX: From<usize>> IntoIterator for &'a Data<T, IDX> ...
// pub struct DataIntoIterator<'a, T, IDX: From<usize>> ...
// impl<'a, T, IDX: From<usize>> Iterator for DataIntoIterator<'a, T, IDX> ...
impl<'a, T, IDX: From<usize>> IntoIterator for &'a mut Data<T, IDX> {
type Item = (IDX, &'a mut T);
type IntoIter = DataIntoIteratorMut<'a, T, IDX>;
fn into_iter(self) -> Self::IntoIter {
DataIntoIteratorMut {
inner: &mut self.inner,
index: 0,
__: std::marker::PhantomData,
}
}
}
pub struct DataIntoIteratorMut<'a, T, IDX: From<usize>> {
pub inner: &'a mut Vec<T>,
pub index: usize,
__: std::marker::PhantomData<IDX>,
}
impl<'a, T, IDX: From<usize>> Iterator for DataIntoIteratorMut<'a, T, IDX> {
type Item = (IDX, &'a mut T);
fn next(&mut self) -> Option<Self::Item> {
if let Some(value) = self.inner.get_mut(self.index) // ERROR!
{
let ret = Some( (IDX::from(self.index), value) );
self.index += 1;
ret
} else {
None
}
}
}
编译器给出以下令人困惑的错误消息:
cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
note: ...so that reference does not outlive borrowed content
note: expected `std::iter::Iterator`
found `std::iter::Iterator`rustc(E0495)
此错误消息对我来说毫无意义。我可以使用不安全的代码获取我想要的数据:
impl<'a, T, IDX: From<usize>> Iterator for DataIntoIteratorMut<'a, T, IDX> {
type Item = (IDX, &'a mut T);
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.inner.len() {
let ptr = self.inner.as_mut_ptr();
unsafe { // is this dangerous?
let value: &'a mut T = &mut *ptr.add(self.index);
let ret = Some( (IDX::from(self.index), value) );
self.index += 1;
ret
}
} else {
None
}
}
}
这可以编译,但我想避免这样的不安全黑客攻击。这个问题有安全的解决方案吗?
解决方案
推荐阅读
- tensorflow - 将多个 GPU 与 Horovod 一起使用是否正常?
- stripe-payments - 如何使用 Stripe Checkout 成功访问 clientReferenceId
- c++ - 如何修复这个 shared_ptr 参考周期?
- php - 如何通过 PHP 文件手动分配用户密码
- python - PyInstaller 陷入无限循环(钩子)
- android-auto - 在 Android Auto 中剪辑视频以完全填满屏幕
- flume - 如果我删除本地文件,flume 会删除远程文件吗?
- flutter - 使用借记卡进行 Flutter 应用内购买
- google-apps-script - 如何使用 Google Adsense 页脚广告代码?
- python - For循环ValueError:一个Series的真值不明确