如何在编译时选择宏?

时间:2015-08-29 22:17:49

标签: macros rust

我有相同宏的不同版本,我希望能够在编译时选择其中一个。

这是我的代码:

macro_rules! macro_a {
    ($identifier:ident) => {
        println!("A: {}", stringify!($identifier));
    }
}

macro_rules! macro_b {
    ($identifier:ident) => {
        println!("B: {}", stringify!($identifier));
    }
}

macro_rules! macro_c {
    ($identifier:ident) => {
        println!("C: {}", stringify!($identifier));
    }
}

macro_rules! choose_macro {
    (a) => {
        const CHOSEN_MACRO: u32 = 1;
    };
    (b) => {
        const CHOSEN_MACRO: u32 = 2;
    };
    (c) => {
        const CHOSEN_MACRO: u32 = 3;
    };
}

choose_macro!(c);

macro_rules! use_macro {
    ($identifier:ident) => {
        match CHOSEN_MACRO {
            1 => macro_a!($identifier),
            2 => macro_b!($identifier),
            3 => macro_c!($identifier),
            _ => unreachable!(),
        }
    }
}

fn main() {
    use_macro!(test);
}

这将按预期打印:

C: test

我想知道是否有更好的方法(使用宏或属性或其他任何东西)。

目前还不清楚是否在编译时选择了宏。 Will Rust会删除匹配,因为它是常量吗?

更新:我更喜欢在代码中选择宏,而不是使用编译器标志。另外,我不想隐藏未选择的宏:我希望能够使用它们的真实名称来使用它们。

1 个答案:

答案 0 :(得分:2)

我建议使用条件编译标志来做这样的事情。见https://doc.rust-lang.org/book/conditional-compilation.html

在您的情况下,它可能看起来像这样:

#[cfg(feature = "feature_a")]
macro_rules! use_macro {
    ($identifier:ident) => {
        println!("A: {}", stringify!($identifier));
    }
}

#[cfg(feature = "feature_b")]
macro_rules! use_macro {
    ($identifier:ident) => {
        println!("B: {}", stringify!($identifier));
    }
}

#[cfg(feature = "feature_c")]
macro_rules! use_macro {
    ($identifier:ident) => {
        println!("C: {}", stringify!($identifier));
    }
}

fn main() {
    use_macro!(test);
}

然后将以下内容添加到您的Cargo.toml文件中:

[features]
feature_a = []
feature_b = []
feature_c = []

如果你想要打印出来" C:test"例如,然后运行以下命令:

cargo run --features feature_c