Here is a macro that counts the number of matched items:
macro_rules! count_items {
($name:ident) => { 1 };
($first:ident, $($rest:ident),*) => {
1 + count_items!($($rest),*)
}
}
fn main() {
const X: usize = count_items!(a);
const Y: usize = count_items!(a, b);
const Z: usize = count_items!(a, b, c);
assert_eq!(1, X);
assert_eq!(2, Y);
assert_eq!(3, Z);
}
Note that the counting is computed at compile time.
For your example, you can do it using accumulation:
macro_rules! count {
($first:ident, $($rest:ident),*) => (
count!($($rest),+ ; 0; $first = 0)
);
($cur:ident, $($rest:ident),* ; $last_index: expr ; $($var:ident = $index:expr)+) => (
count!($($rest),* ; $last_index + 1; $($var = $index)* $cur = $last_index + 1)
);
($cur:ident; $last_index:expr ; $($var:ident = $index:expr)+) => (
#[repr(C)]
enum Count {
$($var = 1 << $index),*,
$cur = 1 << ($last_index + 1),
}
);
}
pub fn main() {
count!(A, B, C, D);
assert_eq!(1, Count::A as usize);
assert_eq!(2, Count::B as usize);
assert_eq!(4, Count::C as usize);
assert_eq!(8, Count::D as usize);
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…