Несколько раз, я столкнулся с сценарием, где необходим метод accessor как для изменяемых, так и для неизменяемых ссылок.
Для ~ 3 строк не проблема дублировать логику, но когда логика становится более сложной, неплохо скопировать большие блоки кода.
Я хотел бы иметь возможность повторно использовать код для обоих.
Предоставляет ли Rust некоторый способ справиться с этим лучше, чем скопировать код или использовать unsafe
casts?
например:.
impl MyStruct {
pub fn get_foo(&self) -> &Bar {
// ~20 lines of code
// --- snip ---
return bar;
}
pub fn get_foo_mut(&mut self) -> &mut Bar {
// ~20 lines of code
// (exactly matching previous code except `bar` is mutable)
// --- snip ---
return bar;
}
}
Вот более подробная выдержка из базы кода, где неизменяемый возвращаемый аргумент был изменен на mutable для поддержки как неизменяемых, так и изменяемых версий функции. Это использует тип обернутого указателя (ConstP
и MutP
для неизменяемых и изменяемых ссылок), но логика функции должна быть ясной.
pub fn face_vert_share_loop<V, F>(f: F, v: V) -> LoopConstP
where V: Into<VertConstP>,
F: Into<FaceConstP>
{
into_expand!(f, v);
let l_first = f.l_first.as_const();
let mut l_iter = l_first;
loop {
if l_iter.v == v {
return l_iter;
}
l_iter = l_iter.next.as_const();
if l_iter == l_first {
break;
}
}
return null_const();
}
pub fn face_vert_share_loop_mut(f: FaceMutP, v: VertMutP) -> LoopMutP {
let l = face_vert_share_loop(f, v);
return unsafe {
// Evil! but what are the alternatives?
// Perform an unsafe `const` to `mut` cast :(
// While in general this should be avoided,
// its 'OK' in this case since input is also mutable.
l.as_mut()
};
}