如何有条件地更改Rust宏的一小部分? [英] How to conditionally change a small part of a Rust macro?
问题描述
我正在建立一个具有 foo
功能的板条箱.这个箱子有一个宏 bar!
,它根据是否设置了 foo
来做细微的事情.
I am building a crate which has the feature foo
. This crate has a macro bar!
that does subtly different things based on whether foo
is set.
我可以复制整个宏:
#[cfg(feature = "foo")]
macro_rules! bar {
// Lots of rules...
( A ) => {
B
}
}
#[cfg(not(feature = "foo"))]
macro_rules! bar {
// Lots of rules...
( A ) => {
C
}
}
这是很多容易出错的重复.两种无效的方法:
That's a lot of error-prone duplication. Two approaches that don't work:
-
我们无法在宏内移动
cfg ,因为它会在板条箱用户的范围内扩展,而该范围未正确设置功能 foo
.
We can't move the
cfg
inside the macro, because then it will expand in the crate user's scope, which does not have featurefoo
appropriately set.
我们不能使用#[doc(hidden)]#[macro_export] macro_rules!自Rust 1.30起,bar_priv_impl __
帮助宏并在帮助宏上使用#[cfg]
,因为用户现在可以请求使用mycrate :: bar;
仅导入 bar!
宏,给出有关未定义 bar_priv_impl __!
的错误.
We can't use a #[doc(hidden)] #[macro_export] macro_rules! bar_priv_impl__
helper macro and use #[cfg]
on the helper macro since Rust 1.30, because users can now request use mycrate::bar;
to only import the bar!
macro, giving errors about how bar_priv_impl__!
is not defined.
有什么方法比完整的宏复制更好吗?如果您要测试的N个功能真的很糟糕,因为您需要 2 n 个重复项.
Is there any way that's better than full macro duplication? It gets really bad if you have N features you're testing on, as you need 2n duplications.
推荐答案
由于Rust 1.30 [...],因为用户现在只能导入
bar!
宏
实际上,该解决方案在Rust 1.30中仅 可行,因为它能够像普通的那样导入宏.请记住,您的宏还可以 具有 use
语句!:
Actually, this solution is only possible in Rust 1.30 because of the ability to import macros like normal. Remember that your macro can also have use
statements!:
#[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)
}
您还可以完全限定助手宏的调用:
You can also fully-qualify your helper macro invocation:
#[macro_export]
macro_rules! bar {
($val:expr) => ($crate::__bar_foo!($val))
}
这篇关于如何有条件地更改Rust宏的一小部分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!