番号付きの実装を定義する方法は、再帰マクロを使用することです。一意の番号はcounting argumentsによって作成できます。この場合、末尾の引数がカウントされます。
この問題は、最初の構造体の番号が最も大きく、最後の構造体のゼロがある場合はインデックスが逆になっています。
数値が一意である必要がある場合は問題ありませんが、この場合、各構造体インデックスはマクロに渡される順序と一致する必要があります。
入力引数は、再帰マクロsee this exampleを使用して元に戻すことができます。
apply_args_reverse!(macro_name, arg1 arg2 arg3)
に展開さ::一般的なマクロを書くために、その可能性を、このマクロを使用する
もちろん
macro_name!(arg3 arg2 arg1)
は、独自に非常に有用ではないthatsの、それがあれば便利です引数は直接記述されるのではなく、引数として渡されます。
これは、次のように各引数の数に展開されるマクロを作る作成するために使用することができます。
struct Foo {_var: bool}
struct Bar {_var: u8}
struct Baz {_var: i16}
trait NumberStruct {
fn struct_number() -> usize;
}
macro_rules! count_args_space {
() => {0_usize};
($_head:tt $($tail:tt)*) => {1_usize + count_args_space!($($tail)*)};
}
macro_rules! number_structs_impl {
(@single $t:tt $($tail:tt)*) => (
impl NumberStruct for $t {
fn struct_number() -> usize {
return count_args_space!($($tail)*);
}
}
);
() => {};
($head:tt $($tail:tt)*) => {
number_structs_impl!(@single $head $($tail)*);
number_structs_impl!($($tail)*);
};
}
macro_rules! apply_args_reverse {
($macro_id:tt [] $($reversed:tt)*) => {
$macro_id!($($reversed) *);
};
($macro_id:tt [$first:tt $($rest:tt)*] $($reversed:tt)*) => {
apply_args_reverse!($macro_id [$($rest)*] $first $($reversed)*);
};
// Entry point, use brackets to recursively reverse above.
($macro_id:tt, $($t:tt)*) => {
apply_args_reverse!($macro_id [ $($t)* ]);
};
}
// Note that both commands below work, and can be swapped to reverse argument order.
// number_structs_impl!(Foo Bar Baz);
apply_args_reverse!(number_structs_impl, Foo Bar Baz);
fn main() {
// see if the numbers are correct
macro_rules! print_numbers {
($($t:tt)*) => ($(
print!("{}:{} ", stringify!($t), $t::struct_number());
)*)
}
print_numbers!(Baz Bar Foo);
println!();
}
お知らせ文を:
number_structs_impl!(Foo Bar Baz);
...と
apply_args_reverse!(number_structs_impl, Foo Bar Baz);
...それぞれの構造体に割り当てられた番号の順序を逆にして、コメントを入れ替えることができます。
注:これは、より簡潔である一方で、マクロ展開が深くを入れ子に取得しているので、それは、ハード・ツー・トラブルシューティングの問題になりやすい、また、より多くの脆弱な私other answerを保ちます(私はこの中には、それがで動作するようになりました少なくとも)。