如何有条件地更改Rust宏的一小部分?

时间:2018-10-26 22:48:54

标签: macros rust

我正在建立一个具有foo功能的板条箱。这个板条箱有一个宏bar!,它根据是否设置了foo来做一些细微的事情。

我可以复制整个宏:

#[cfg(feature = "foo")]
macro_rules! bar {
    // Lots of rules...

    ( A ) => {
        B
    }
}

#[cfg(not(feature = "foo"))]
macro_rules! bar {
    // Lots of rules...

    ( A ) => {
        C
    }
}

这是很多容易出错的重复。两种无效的方法:

  • 我们无法在宏内移动cfg,因为这样它将在板条箱用户的范围内扩展,该范围没有适当设置功能foo

    < / li>
  • 从Rust 1.30开始,我们不能使用#[doc(hidden)] #[macro_export] macro_rules! bar_priv_impl__帮助宏,而不能在辅助宏上使用#[cfg],因为用户现在可以请求use mycrate::bar;只导入{{ 1}}宏,给出有关如何定义bar!的错误。

有什么方法比完整的宏复制更好吗?如果您要测试的N个功能真的很糟糕,因为您需要 2 n 个重复项。

1 个答案:

答案 0 :(得分:2)

  

由于Rust 1.30 [...],因为用户现在只能导入bar!

实际上,该解决方案在Rust 1.30中仅 可行,因为它能够像普通的那样导入宏。请记住,您的宏还可以 具有use条语句!:

#[macro_export]
macro_rules! bar {
    ($val:expr) => {{
        use $crate::__bar_foo;
        __bar_foo!($val)
    }}
}

#[cfg(feature = "foo")]
#[macro_export]
macro_rules! __bar_foo {
    ($val:expr) => ($val + 1)
}

#[cfg(not(feature = "foo"))]
#[macro_export]
macro_rules! __bar_foo {
    ($val:expr) => ($val - 1)
}

您还可以完全限定助手宏的调用:

#[macro_export]
macro_rules! bar {
    ($val:expr) => ($crate::__bar_foo!($val))
}