目前,std::ops::IndexMut
在Rust中的类型上实现特征要求我也实现std::ops::Index
特征.这些实现的主体最终几乎完全相同.例如:
use std::ops::{Index, IndexMut};
enum IndexType {
A,
B,
}
struct Indexable {
a: u8,
b: u8,
}
impl Index<IndexType> for Indexable {
type Output = u8;
fn index<'a>(&'a self, idx: IndexType) -> &'a u8 {
match idx {
IndexType::A => &self.a,
IndexType::B => &self.b,
}
}
}
impl IndexMut<IndexType> for Indexable {
fn index_mut<'a>(&'a mut self, idx: IndexType) -> &'a mut u8 {
match idx {
IndexType::A => &mut self.a,
IndexType::B => &mut self.b,
}
}
}
fn main() {}
Run Code Online (Sandbox Code Playgroud)
这是有效的,显然对于琐碎的类型,这不是一个严重的问题,但对于更复杂的类型和更有趣的索引,这很快变得费力且容易出错.我正试图找到一种方法来统一这个代码,但是没有任何东西可以跳出来,但我觉得必须/应该是一种方法来做到这一点,而不必复制和粘贴.有什么建议?我错过了什么?
不幸的是,这切割了Rust现在并不擅长的一些事情.我能想到的最干净的解决方案是:
macro_rules! as_expr {
($e:expr) => { $e };
}
macro_rules! borrow_imm { ($e:expr) => { &$e } }
macro_rules! borrow_mut { ($e:expr) => { &mut $e } }
macro_rules! impl_index {
(
<$idx_ty:ty> for $ty:ty,
($idx:ident) -> $out_ty:ty,
$($body:tt)*
) => {
impl ::std::ops::Index<$idx_ty> for $ty {
type Output = $out_ty;
fn index(&self, $idx: $idx_ty) -> &$out_ty {
macro_rules! index_expr { $($body)* }
index_expr!(self, borrow_imm)
}
}
impl ::std::ops::IndexMut<$idx_ty> for $ty {
fn index_mut(&mut self, $idx: $idx_ty) -> &mut $out_ty {
macro_rules! index_expr { $($body)* }
index_expr!(self, borrow_mut)
}
}
};
}
enum IndexType { A, B }
struct Indexable { a: u8, b: u8 }
impl_index! {
<IndexType> for Indexable,
(idx) -> u8,
($this:expr, $borrow:ident) => {
match idx {
IndexType::A => $borrow!($this.a),
IndexType::B => $borrow!($this.b),
}
}
}
fn main() {
let mut x = Indexable { a: 1, b: 2 };
x[IndexType::A] = 3;
println!("x {{ a: {}, b: {} }}", x[IndexType::A], x[IndexType::B]);
}
Run Code Online (Sandbox Code Playgroud)
短版本是:我们转向的本体index
/ index_mut
成宏,以便我们可以替换一个的名称不同宏,给出的表达式,扩展为任一 &expr
或&mut expr
.我们也必须重新拍摄self
参数(使用不同的名称),因为self
是很奇怪的锈了,我放弃了试图使其很好地工作.
归档时间: |
|
查看次数: |
110 次 |
最近记录: |