我正在建造一个具有该功能的板条箱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
}
}
Run Code Online (Sandbox Code Playgroud)
这是很多容易出错的重复。两种不起作用的方法:
我们无法移动cfg宏内部,因为这样它将在板条箱用户的范围内扩展,而该范围没有foo适当设置的功能。
从 Rust 1.30 开始,我们不能使用辅助宏并在辅助宏上#[doc(hidden)] #[macro_export] macro_rules! bar_priv_impl__使用,因为用户现在可以请求仅导入宏,从而给出有关如何未定义的错误。#[cfg]use mycrate::bar;bar!bar_priv_impl__!
有没有比完全宏复制更好的方法?如果您要测试 N 个功能,情况会变得非常糟糕,因为您需要2 n 个重复项。
从 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)
}
Run Code Online (Sandbox Code Playgroud)
您还可以完全限定您的辅助宏调用:
#[macro_export]
macro_rules! bar {
($val:expr) => ($crate::__bar_foo!($val))
}
Run Code Online (Sandbox Code Playgroud)