Move modified link from mutable object
I have an iterator over enum
that has a mutable reference in one of its variants. Now I want to move this link self
and get it back. To avoid using two mutable references to the same object at the same time, I want to change the enumeration variant self
to one that has no reference. Below is a sample code:
enum Test<'a> {
A(&'a mut usize),
B,
}
impl<'a> Iterator for Test<'a> {
type Item = &'a mut usize;
fn next(&mut self) -> Option<Self::Item> {
match *self {
Test::A(r) => Some(r), // TODO: return mutable reference and change self to B
Test::B => None,
}
}
}
fn main() {
let mut v = 1;
let mut it = Test::A(&mut v);
it.next();
}
The question is related to Change a selector to match if the selector is a mutable reference , but that solution doesn't work here.
+3
source to share
1 answer
I would use swap
:
fn next(&mut self) -> Option<Self::Item> {
if let Test::A(_) = *self {
let mut to_swap = Test::B;
std::mem::swap(self, &mut to_swap);
match to_swap {
Test::A(r) => Some(r),
_ => unreachable!(), // never reached
}
} else {
None
}
}
You can use the helper function like this:
impl<'a> Iterator for Test<'a> {
type Item = &'a mut usize;
fn next(&mut self) -> Option<Self::Item> {
if let Test::A(_) = *self {
let mut to_swap = Test::B;
std::mem::swap(self, &mut to_swap);
to_swap.consume_as_a()
} else {
None
}
}
}
impl<'a> Test<'a> {
fn consume_as_a(self) -> Option<&'a mut usize> {
match self {
Test::A(r) => Some(r),
_ => None,
}
}
}
+3
source to share