Могу ли я определить макрос, который расширится до вызова функции? - PullRequest
0 голосов
/ 11 марта 2020

Я (наивно) попробовал это, но на экране ничего не печатается:

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 Ответ

2 голосов
/ 11 марта 2020

Да, и нет.

Прежде всего, concat! генерирует строку, поэтому ваш код по сути такой же, как если бы вы написали:

fn main() {
    "foobool(true)";
    "fooi32(1)";
}

, что не op.

Чтобы сгенерировать 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...