如何为特征的每个实现自动生成递增的数字标识符?
How to automatically generate incrementing number identifiers for each implementation of a trait?
我有一个 Component
特征,它有一个 return 索引的方法,像这样:
trait Component {
fn index(&self) -> usize;
}
这些索引用于在位集中设置标志。例如,Component
特征对象 return 索引为 5 将导致在容器中设置第 5 位。
目前我 return 手动为每个实现类型创建 运行 索引:
struct Foo;
struct Bar;
impl Component for Foo {
fn index(&self) -> usize { 0 }
}
impl Component for Bar {
fn index(&self) -> usize { 1 }
}
特征对象被插入到容器中,该容器使用位集跟踪添加的组件:
struct Container<'a> {
components: Vec<Component + 'a>,
bits: BitSet
}
impl<'a> Container<'a> {
fn add<T: Component + 'a>(&mut self, component: T) {
self.components.push(component);
self.bits.set(component.index());
}
}
这很好用,但是手动 return 为每个实现类型创建索引很麻烦。我怎样才能使每个实现类型都自动获取其索引?
您可以定义一个递归调用自身的宏:
macro_rules! impl_component {
// Empty case to end the recursion
($n:expr ;) => {};
// Match the current count, the current type, and whatever else comes after
($n:expr ; $t:ty $(, $rest:tt)*) => {
impl Component for $t {
fn index(&self) -> usize { $n }
}
// Recurse, incrementing counter and only passing the remaining params
impl_component!($n + 1; $($rest),*);
};
// For the first recursion, set the counter initial value to zero
($($types:tt),+) => { impl_component!(0; $($types),*); };
}
impl_component!(Foo, Bar, Baz);
生成的代码将包括这样的实现:
impl Component for Baz {
fn index(&self) -> usize { 0 + 1 + 1 }
}
编译器会将这些表达式折叠成文字,因此结果等同于您想要的结果。
我有一个 Component
特征,它有一个 return 索引的方法,像这样:
trait Component {
fn index(&self) -> usize;
}
这些索引用于在位集中设置标志。例如,Component
特征对象 return 索引为 5 将导致在容器中设置第 5 位。
目前我 return 手动为每个实现类型创建 运行 索引:
struct Foo;
struct Bar;
impl Component for Foo {
fn index(&self) -> usize { 0 }
}
impl Component for Bar {
fn index(&self) -> usize { 1 }
}
特征对象被插入到容器中,该容器使用位集跟踪添加的组件:
struct Container<'a> {
components: Vec<Component + 'a>,
bits: BitSet
}
impl<'a> Container<'a> {
fn add<T: Component + 'a>(&mut self, component: T) {
self.components.push(component);
self.bits.set(component.index());
}
}
这很好用,但是手动 return 为每个实现类型创建索引很麻烦。我怎样才能使每个实现类型都自动获取其索引?
您可以定义一个递归调用自身的宏:
macro_rules! impl_component {
// Empty case to end the recursion
($n:expr ;) => {};
// Match the current count, the current type, and whatever else comes after
($n:expr ; $t:ty $(, $rest:tt)*) => {
impl Component for $t {
fn index(&self) -> usize { $n }
}
// Recurse, incrementing counter and only passing the remaining params
impl_component!($n + 1; $($rest),*);
};
// For the first recursion, set the counter initial value to zero
($($types:tt),+) => { impl_component!(0; $($types),*); };
}
impl_component!(Foo, Bar, Baz);
生成的代码将包括这样的实现:
impl Component for Baz {
fn index(&self) -> usize { 0 + 1 + 1 }
}
编译器会将这些表达式折叠成文字,因此结果等同于您想要的结果。