Могу ли я определить макрос, который будет расширяться до вызова функции?
Я (наивно) пробовал это, но на экран ничего не выводится:
macro_rules! foo {
($suffix:tt, $arg:expr) => {
concat!("foo", $suffix, "(", $arg, ")");
};
}
fn foo_i32(x: i32) {
println!("i32 {}", x);
}
fn foo_bool(x: bool) {
println!("bool {}", x);
}
fn main() {
foo!("bool", true);
foo!("i32", 1);
}
1 ответ
Решение
Да и нет.
Первый из, concat!
генерирует строку, поэтому ваш код по сути такой же, как если бы вы написали:
fn main() {
"foobool(true)";
"fooi32(1)";
}
который не работает.
Чтобы сгенерировать код на Rust, макрос не обязательно должен использовать строки:
macro_rules! foo {
($suffix:tt, $arg:expr) => {
$suffix($arg);
};
}
которую вы могли бы назвать foo!(foo_bool, true);
.
Если, однако, вы хотите построить имя foo_bool
от foo
а также bool
, вам нужно использовать concat_idents
, который в настоящее время нестабилен и вряд ли станет стабильным в ближайшее время (потому что вызывает некоторые проблемы с гигиеной):
#![feature(concat_idents)]
macro_rules! foo {
($suffix:tt, $arg:expr) => {
concat_idents!(foo_, $suffix)($arg);
};
}
fn foo_i32(x: i32) {
println!("i32 {}", x);
}
fn foo_bool(x: bool) {
println!("bool {}", x);
}
fn main() {
foo!(bool, true);
foo!(i32, 1);
}