【发布时间】:2021-11-17 08:34:49
【问题描述】:
我想在 Rust 中实现一个表类型,所以我有下面的代码:
use std::ops::{Index, IndexMut};
#[derive(Clone)]
pub struct Table<T>
where
T: Clone,
{
row: usize,
col: usize,
data: Vec<Vec<T>>,
}
impl<T> Table<T>
where
T: Clone,
{
pub fn new(row: usize, col: usize) -> Self {
let mut t = Table {
row,
col,
data: Vec::<Vec<T>>::with_capacity(row),
};
t.data.resize(row, Vec::<T>::with_capacity(col));
t
}
pub fn size(&self) -> (usize, usize) {
(self.row(), self.col())
}
pub fn col(&self) -> usize {
self.col
}
pub fn row(&self) -> usize {
self.row
}
pub fn cell_iter(&self) -> TableCellIter<T> {
TableCellIter {
table: self,
row: 0,
col: 0,
}
}
pub fn cell_iter_mut(&mut self) -> TableCellIterMut<'_, T> {
TableCellIterMut {
table: self,
row:0,
col:0,
}
}
}
impl<T> Index<(usize, usize)> for Table<T>
where
T: Clone,
{
type Output = T;
fn index(&self, (row, col): (usize, usize)) -> &Self::Output {
if row >= self.row() {
panic!("out of range")
}
&self.data[row][col]
}
}
impl<T> IndexMut<(usize, usize)> for Table<T>
where
T: Clone,
{
fn index_mut(&mut self, (row, col): (usize, usize)) -> &mut Self::Output {
while self.data.len() <= row {
self.data.push(Vec::<T>::with_capacity(self.col()));
}
&mut self.data[row][col]
}
}
pub struct TableCellIter<'a, T>
where
T: Clone,
{
table: &'a Table<T>,
row: usize,
col: usize,
}
impl<'a, T> Iterator for TableCellIter<'a, T>
where
T: Clone,
{
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.col == self.table.col() {
self.row += 1;
self.col = 0;
}
if self.row >= self.table.row() {
return None;
}
let ref cell = self.table[(self.row, self.col)];
self.col += 1;
Some(cell)
}
}
pub struct TableCellIterMut<'a, T>
where
T: Clone,
{
table: &'a mut Table<T>,
row: usize,
col: usize,
}
impl<'a, T> Iterator for TableCellIterMut<'a, T>
where
T: Clone,
{
type Item = &'a mut T;
fn next<'b: 'a>(&'b mut self) -> Option<Self::Item>
{
if self.col == self.table.col() {
self.row += 1;
self.col = 0;
}
if self.row >= self.table.row() {
return None;
}
let ref mut cell = self.table[(self.row, self.col)];
self.col += 1;
Some(cell)
}
}
TableCellIter 类型工作正常的地方,TableCellIterMut 不能。编译器警告我:
error[E0195]: lifetime parameters or bounds on method `next` do not match the trait declaration
--> src/lib.rs:125:12
|
125 | fn next<'b: 'a>(&'b mut self) -> Option<Self::Item>
| ^^^^^^^^ lifetimes do not match method in trait
error: aborting due to previous error
For more information about this error, try `rustc --explain E0195`.
error: could not compile `sample`
但是如果我删除 TableCellIterMut 下一个中的生命周期边界:
fn next(&mut self) -> Option<Self::Item>
似乎无法推断下一个生命周期参数:
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/lib.rs:135:28
|
135 | let ref mut cell = self.table[(self.row, self.col)];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime defined on the method body at 126:13...
--> src/lib.rs:126:13
|
126 | fn next(&mut self) -> Option<Self::Item>
| ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:135:28
|
135 | let ref mut cell = self.table[(self.row, self.col)];
| ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 119:6...
--> src/lib.rs:119:6
|
119 | impl<'a, T> Iterator for TableCellIterMut<'a, T>
| ^^
note: ...so that the types are compatible
--> src/lib.rs:127:5
|
127 | / {
128 | | if self.col == self.table.col() {
129 | | self.row += 1;
130 | | self.col = 0;
... |
137 | | Some(cell)
138 | | }
| |_____^
= note: expected `Iterator`
found `Iterator`
error: aborting due to previous error
我的问题是,为什么 TableCellIter 中的 next 是正确的,而 TableCellIterMut 中的 next 是错误的?
如何正确实现下一个?
【问题讨论】: